/usr/src/suites/security/audit/src/lib/ksh/audit_zone.ksh
Korn Shell | 676 lines | 491 code | 66 blank | 119 comment | 54 complexity | 64f8d55293bd17b12ba241683868ff05 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception
- #
- # CDDL HEADER START
- #
- # The contents of this file are subject to the terms of the
- # Common Development and Distribution License (the "License").
- # You may not use this file except in compliance with the License.
- #
- # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- # or http://www.opensolaris.org/os/licensing.
- # See the License for the specific language governing permissions
- # and limitations under the License.
- #
- # When distributing Covered Code, include this CDDL HEADER in each
- # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- # If applicable, add the following below this CDDL HEADER, with the
- # fields enclosed by brackets "[]" replaced with your own identifying
- # information: Portions Copyright [yyyy] [name of copyright owner]
- #
- # CDDL HEADER END
- #
- #
- # Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
- #
- . ${CTI_SUITE}/include/commands
- . ${CTI_SUITE}/include/vars
- . ${CTI_SUITE}/lib/audit_tx
- #
- # NAME
- # is_global
- #
- # ARGUMENTS
- #
- # DESCRIPTION
- # Function returns 0 on success - called from the global zone or 1 in
- # case of execution from the local zone.
- function is_global
- {
- typeset -r fn=is_global
- debug "${fn}: entered."
- if [[ "$(${ZONENAME})" != "global" ]]; then
- debug "${fn}: called from the local zone."
- debug "${fn}: exited (1)."
- return 1
- fi
- debug "${fn}: called from the global zone."
- debug "${fn}: exited (0)."
- return 0
- }
- #
- # NAME
- # zone_prepare
- #
- # ARGUMENTS
- # arg1 zonetype [default=sparse|wholeroot]
- # arg2 zonename - must be uniqueue across the system (tested)
- # arg3 zonepath [default=/zones]
- #
- #
- # DESCRIPTION
- # Function creates and prepares for boot local zone zonename (arg2) of
- # type zonetype (arg1) mounted in the zonepath/zonename (arg3). Function
- # returns 0 on success - zone successfully created and installed, or 1 in
- # case of any error found during function processing. Function keeps
- # system clean/unconfigured if returns with 1.
- #
- # In case the sparse zone ought to be created (arg1 = default|sparse),
- # then /lib, /platform, /sbin, /usr are to be shared between global and
- # the local zone. Note, that currently the sparse zone configuration for
- # the ipkg zone is not supported, thus such a combination triggers the
- # error and the function returns 1.
- #
- # Note, that this function does not support branded zone creation; which
- # means, that the brand = native|ipkg for all zone configuration created
- # by this function.
- #
- # Programmers note - the function is currently quite monolithic; and it's
- # like that by purpose since the initial programmer thinks that splitting
- # it may confuse consumers by using further split parts of the function.
- # It could be implemented in the future, but such consolidating functions
- # simplifying zone_prepare() would have to have again strong internal
- # checks of the arguments (sanity checks). For now it seems to be
- # reasonable to let the function flow as it is..
- function zone_prepare
- {
- typeset -r fn=zone_prepare
- debug "${fn}: entered."
- if (( $# != 3 )); then
- cti_report "${fn}: bad amount of args ($#)"
- debug "${fn}: exited (1)."
- return 1
- fi
- is_global
- if (( $? != 0 )); then
- cti_report "Cannot be executed from the local zone."
- debug "${fn}: Incorrectly executed from the local zone."
- debug "${fn}: exited (1)."
- return 1
- fi
- typeset i # temp variable for cycles
- typeset j # temp variable for cycles
- typeset rpasswd # root password for the zone
- typeset hexlabel # hexlabel for TX enabled systems
- typeset tmpfile # temporary file
- typeset zonetype="${1}"
- typeset -r zonename="${2}"
- typeset zonepath="${3}"
- typeset zonebrand="native"
- typeset -r timezone="$(${AWK} -F= '/^TZ/ { print $2 }' /etc/TIMEZONE)"
- typeset def_zonexml="/etc/zones/SUNWdefault.xml"
- typeset ipg_zonexml="/etc/zones/SUNWipkg.xml"
- if [[ "${zonepath}" == "default" ]]; then
- zonepath="/zones"
- fi
- if [[ "${zonetype}" == "default" ]]; then
- zonetype="sparse"
- fi
- debug "${fn}: zonetype=${zonetype}"
- debug "${fn}: zonename=${zonename}"
- debug "${fn}: zonepath=${zonepath}"
- #
- # Some sanity checks:
- case "${zonetype}" in
- "sparse")
- #
- # ipkg zone brand testing
- if [[ ! -f "${def_zonexml}" ]]; then
- cti_report "Cannot access ${def_zonexml}."
- debug "${fn}: no such file ${def_zonexml}"
- debug "${fn}: exited (1)."
- return 1
- fi
- if [[ -n "$(${FGREP} brand=\"ipkg\" ${def_zonexml})" ]]; then
- cti_report "Sparse zone not supported on ipkg systems"
- debug "${fn}: (default) system detected as brand=ipkg."
- debug "${fn}: Falling back to the wholeroot zone."
- zonetype="wholeroot"
- fi
- if [[ -f "${ipg_zonexml}" ]]; then
- cti_report "Sparse zone not supported on ipkg systems"
- debug "${fn}: Falling back to the wholeroot zone."
- zonetype="wholeroot"
- fi
- ;;
- "wholeroot")
- ;;
- *)
- cti_report "Unknown zone type build requested (${zonetype})"
- debug "${fn}: exited (1)."
- return 1
- ;;
- esac
- #
- # XXX - The following code is just a workaround for badly behaving zones
- # and zone configuration in OpenSolaris. Bear in mind, that the XXX
- # steps are just a raw patch and can be removed once the particular bugs
- # are resolved.
- # XXX - 1) set the zonebrand to ipkg - Bug 10950
- if [[ -x "/usr/sbin/beadm" ]]; then
- zonebrand="ipkg"
- debug "${fn}: zonebrand changed: zonebrand=${zonebrand}"
- fi
- #
- # XXX - 2) create a zfs filesystem for the zone - Bug 10455
- if [[ "${zonebrand}" == "ipkg" ]]; then
- ${ZFS} create -o mountpoint=/zones rpool/zones
- fi
- #
- # check whether the system is TX enabled
- if [[ "$(${SVCS} -o state svc:/system/labeld:default 2>/dev/null | \
- ${AWK} '$1 !~ /STATE/ { print $1 }')" == "online" ]]; then
- zonebrand="labeled"
- debug "${fn}: zonebrand changed: zonebrand=${zonebrand}"
- hexlabel="$(${ATOHEXLABEL} "${TX_ZONE_LABEL}")"
- if ! add_tnzonecfg_data "${zonename}" "${hexlabel}"; then
- cti_report "Unable to update ${TNZONECFG}."
- debug "${fn}: exited (1)."
- return 1
- fi
- if ! add_tnrhtp_data "${zonename}" "${hexlabel}"; then
- cti_report "Unable to update ${TNRHTP}."
- debug "${fn}: exited (1)."
- return 1
- fi
- if ! ${TNCHKDB} 1>/dev/null 2>/dev/null; then
- cti_report "Errors detected in TX configuration."
- cti_report "See: tnchkdb(1M) for more information."
- debug "${fn}: exited (1)."
- return 1
- fi
- ${SVCADM} restart svc:/network/tnctl
- debug "${fn}: svc:/network/tnctl restarted"
- fi
- if [[ -n "$(${ZONEADM} list -i | ${FGREP} ^${zonename}$)" ]]; then
- cti_report "Zonename ${zonename} already exists in the system"
- debug "${fn}: exited (1)."
- return 1
- fi
- zonepath="${zonepath}/${zonename}"
- if [[ -d "${zonepath}" ]]; then
- cti_report "Zonepath ${zonepath} already exists in the system"
- debug "${fn}: exited (1)."
- return 1
- fi
- #
- # Configure the zone - ${zonename}
- ${ZONECFG} -z "${zonename}" -f - << __EOConfig__
- create -b
- set zonepath=${zonepath}
- set brand=${zonebrand}
- $(if [[ "${zonetype}" == "sparse" ]]; then \
- for i in /lib /platform /sbin /usr; do \
- print "add inherit-pkg-dir"; \
- print "set dir=${i}"; \
- print "end"; \
- done; fi)
- commit
- exit
- __EOConfig__
- if (( $? != 0 )); then
- cti_report "zone ${zonename} configuration failed"
- debug "${fn}: exited (1)."
- return 1
- fi
- debug "${fn}: zone ${zonename} successfully configured."
- #
- # Install the zone
- ${ZONEADM} -z "${zonename}" install
- if (( $? != 0 )); then
- cti_report "zone ${zonename} installation failed"
- ${ZONEADM} -z "${zonename}" delete
- debug "${fn}: zone ${zonename} configuration deleted."
- debug "${fn}: exited (1)."
- return 1
- fi
- debug "${fn}: zone ${zonename} successfully installed."
- #
- # Ready the zone
- ${ZONEADM} -z "${zonename}" ready
- #
- # Do a pre-boot zone configuration - generate sysidcfg(4)
- typeset nameservice="NONE"
- typeset nameservice_tmp="$(${GREP} ^hosts: /etc/nsswitch.conf | ${AWK} \
- '{
- i = 2;
- while ( i < NF ) {
- if ( substr($i, 1) == "[" ) {
- i++;
- continue;
- };
- print $i;
- i++;
- };
- }')"
-
- # the first available NIS|DNS is set up as a name service for the zone
- for nameservice_tmp in ${nameservice_tmp}; do
- case "${nameservice_tmp}" in
- "dns")
- debug "${fn}: DNS name service recognized and used."
- if [[ ! -f /etc/resolv.conf ]]; then
- continue
- fi
- nameservice="DNS"
- i="$(${GREP} ^domain /etc/resolv.conf | ${TAIL} -1 | \
- ${AWK} '{ print $2 }' | \
- ${TR} "[:upper:]" "[:lower:]")"
- if [[ -z "${i}" ]]; then
- debug "${fn}: no domain definition found in "\
- "the /etc/resolv.conf."
- i="$(${HOSTNAME})"
- j="$(${HOST} ${i})"
- j="${j%% *}"
- eval i="\${j#$i.}"
- debug "${fn}: will use domain_name=${i}"
- fi
- nameservice="${nameservice} {domain_name=${i}"
- j=
- for i in $(${GREP} ^nameserver /etc/resolv.conf | \
- ${HEAD} -3 | ${AWK} '{ print $2 }'); do
- j="${j:+${j},}"
- j="${j}${i}"
- done
- nameservice="${nameservice} name_server=${j}"
- i="$(${GREP} ^search /etc/resolv.conf | ${TAIL} -1 | \
- ${AWK} '{
- i = 2;
- while ( i < NF && i < 8) {
- if (i > 2) {
- printf "%s", ",";
- }
- printf "%s", $i;
- i++;
- }
- }')"
- if [[ -n "${i}" ]]; then
- nameservice="${nameservice} search=${i}}"
- else
- nameservice="${nameservice}}"
- fi
- break
- ;;
- "nis")
- debug "${fn}: NIS name service recognized and used."
- nameservice="NIS"
- i="$(${DOMAINNAME} | ${TR} "[:upper:]" "[:lower:]")"
- nameservice="${nameservice} {domain_name=${i}"
- i="$(${YPWHICH} | ${TR} "[:upper:]" "[:lower:]")"
- if [[ -z "${i}" ]]; then
- cti_report "No NIS server configured."
- nameservice=
- continue;
- fi
- j="$(${GETENT} hosts ${i} | ${AWK} '{ print $1"="$2 }')"
- if [[ -z "${j}" ]]; then
- cti_report "Cannot resolve host name for ${i}."
- nameservice=
- continue;
- fi
- if [[ "${j%%=*}" == "${i}" ]]; then
- cti_report "NIS server configured as an" \
- "IP address not a hostname."
- i="${j##*=}"
- fi
- j="${j%%=*}"
- nameservice="${nameservice} name_server=${i}(${j})}"
- break
- ;;
- *)
- cti_report "Service ${nameservice_tmp} not supported."
- continue
- ;;
- esac
- done
- debug "${fn}: finished constructing name_service=${nameservice}"
- # XXX - 3) use crypted password (traditional unix) - Bug 6863728
- # rpasswd="$(${AWK} -F: '/^root:/ { print $2 }' /etc/shadow)"
- rpasswd="MW8T79hI9lQA6" # tet123
- if [[ "${zonebrand}" == "labeled" ]]; then
- ${CAT} > "${zonepath}/root/etc/sysidcfg" << __EOsysidcfg__
- system_locale=C
- terminal=xterm
- security_policy=NONE
- name_service=${nameservice}
- timezone=${timezone}
- root_password=${rpasswd}
- nfs4_domain=dynamic
- network_interface=PRIMARY {hostname=${zonename}}
- __EOsysidcfg__
-
- else
- ${CAT} > "${zonepath}/root/etc/sysidcfg" << __EOsysidcfg__
- system_locale=C
- terminal=xterm
- network_interface=NONE {hostname=${zonename}}
- security_policy=NONE
- name_service=${nameservice}
- timezone=${timezone}
- root_password=${rpasswd}
- nfs4_domain=dynamic
- __EOsysidcfg__
- fi
- debug "${fn}: ${zonepath}/root/etc/sysidcfg created."
- # XXX - 4) ksh bug - 6946957, 6950013
- #debug "${fn}: $(${CAT} ${zonepath}/root/etc/sysidcfg)"
- #
- # Update zone nodename (TX enabled system fails to initiate nodename
- # based on the sysidcfg contents (hostname=).
- if [[ "${zonebrand}" == "labeled" ]]; then
- print "${zonename}" > ${zonepath}/root/etc/nodename
- debug "${fn}: ${zonepath}/root/etc/nodename nodename" \
- "set to ${zonename}"
- fi
- #
- # Update the GZ loopback IPv4 address to be resolved from ${zonename}.
- if [[ "${zonebrand}" == "labeled" ]]; then
- tmpfile="$($MKTEMP /tmp/hosts.XXXXXXXX)"
- ${SED} -e "s/^\(127.0.0.1\)\(.*\)$/\1 ${zonename} \2/" \
- /etc/inet/hosts > ${tmpfile} 2>/dev/null
- mv ${tmpfile} /etc/inet/hosts 2>/dev/null
- debug "${fn}: /etc/inet/hosts regenerated."
- fi
- debug "${fn}: exited (0)."
- return 0
- }
- #
- # NAME
- # zone_destroy
- #
- # ARGUMENTS
- # arg1 zonename
- #
- # DESCRIPTION
- # Function uninstalls the zone and deletes the zone configuration.
- # Function returns 0 on success - zone successfully removed,
- # or 1 in case of any error found during function processing.
- function zone_destroy
- {
- typeset -r fn=zone_destroy
- debug "${fn}: entered."
- if (( $# != 1 )); then
- cti_report "${fn}: bad amount of args ($#)"
- debug "${fn}: exited (1)."
- return 1
- fi
- is_global
- if (( $? != 0 )); then
- cti_report "Cannot be executed from the local zone."
- debug "${fn}: Incorrectly executed from the local zone."
- debug "${fn}: exited (1)."
- return 1
- fi
- typeset -r zonename="${1}"
- typeset zonestate=
- debug "${fn}: zonename=${zonename}"
- #
- # halt && uninstall && unconfigure
- zonestate="$(${ZONEADM} list -pc | \
- ${NAWK} -F\: '$2 ~ /'"${zonename}"'/ { print $3 }')"
- debug "${fn}: ${zonename} - zonestate=${zonestate}"
- #
- # XXX - The following code is just a workaround for badly behaving zones
- # and zone configuration in OpenSolaris. Bear in mind, that the XXX
- # steps are just a raw patch and can be removed once the particular bugs
- # are resolved.
- # XXX - 0) set the brand of the zone
- typeset -r zonebrand="$(${ZONEADM} list -pc | \
- ${NAWK} -F\: '$2 ~ /'"${zonename}"'/ { print $6 }')"
- if [[ -n "${zonestate}" ]]; then
- case "${zonestate}" in
- "running")
- ${ZONEADM} -z ${zonename} halt
- ${ZONEADM} -z ${zonename} uninstall -F
- ${ZONECFG} -z ${zonename} delete -F
- ;;
- "installed"|"incomplete")
- ${ZONEADM} -z ${zonename} uninstall -F
- ${ZONECFG} -z ${zonename} delete -F
- ;;
- "configured")
- ${ZONECFG} -z ${zonename} delete -F
- ;;
- *)
- cti_report "Unknown zone state: ${zonestate}"
- ;;
- esac
- if [[ -n "$(${ZONEADM} list -pc | ${FGREP} ":${zonename}:")" ]]
- then
- cti_report "Zone: ${zonename} wasn't fully removed."
- debug "${fn}: $(${ZONEADM} list -pc | \
- ${FGREP} ":${zonename}:")"
- debug "${fn}: exited (1)."
- return 1
- fi
- # XXX - 1) destroy a zfs filesystem for the zone - Bug 10455
- if [[ "${zonebrand}" == "ipkg" || \
- "${zonebrand}" == "labeled" ]]; then
- ${ZFS} destroy -rf rpool/zones
- fi
- if [[ "${zonebrand}" == "labeled" ]]; then
- del_tnzonecfg_data "${zonename}"
- del_tnrhtp_data "${zonename}"
- if ! ${TNCHKDB} 1>/dev/null 2>/dev/null; then
- cti_report "Errors detected in TX config."
- cti_report "See: tnchkdb(1M) for more info."
- debug "${fn}: exited (1)."
- return 1
- fi
- ${SVCADM} restart svc:/network/tnctl
- debug "${fn}: svc:/network/tnctl restarted"
- fi
- else
- cti_report "No such zone ${zonename} installed/running."
- cti_report "Halt/Uninstall phase for the ${zonename} skipped."
- fi
- #
- # Remove the ${tzone} from the /etc/inet/hosts.
- if [[ "${zonebrand}" == "labeled" ]]; then
- tmpfile="$($MKTEMP /tmp/hosts.XXXXXXXX)"
- ${SED} -e "s/^\(127.0.0.1\) ${zonename} \(.*\)$/\1\2/" \
- /etc/inet/hosts > ${tmpfile} 2>/dev/null
- mv ${tmpfile} /etc/inet/hosts 2>/dev/null
- debug "${fn}: /etc/inet/hosts regenerated."
- fi
- debug "${fn}: exited (0)."
- return 0
- }
- #
- # NAME
- # zone_booted
- #
- # ARGUMENTS
- # arg1 zonename
- # arg2 timeout
- #
- # DESCRIPTION
- # Function waits until the zone zonename/arg1 has been in booted state.
- # Fully booted state is checked via online state of the
- # svc:/milestone/sysconfig:default milestone service. Checking against
- # this service overcomes the issue with reboot of the zone after its
- # reconfiguration based on the sysidcfg(4) values. Function returns 0 on
- # success - zone is reconfigured / booted. If the timeout/arg2 is reached
- # without successfully detected zone in booted state, function returns 1.
- # If the timeout equals zero, function blocks/cycles in 5 second steps
- # untill the zone is fully booted.
- function zone_booted
- {
- typeset -r fn=zone_booted
- debug "${fn}: entered."
- if (( $# != 2 )); then
- cti_report "${fn}: bad amount of args ($#)"
- debug "${fn}: exited (1)."
- return 1
- fi
- is_global
- if (( $? != 0 )); then
- cti_report "Cannot be executed from the local zone."
- debug "${fn}: Incorrectly executed from the local zone."
- debug "${fn}: exited (1)."
- return 1
- fi
- typeset -r zonename="${1}"
- typeset -i timeout="${2}"
- typeset -i blocking_loop=0
- typeset sysconfig_state=
- debug "${fn}: zonename=${zonename}"
- debug "${fn}: timeout=${timeout}"
- if (( timeout == 0 )); then
- blocking_loop=1
- fi
- while ${TRUE}; do
- sysconfig_state="$(${ZLOGIN} ${zonename} ${SVCS} -Ho state \
- svc:/milestone/sysconfig:default)"
- if [[ "${sysconfig_state}" == "online" ]]; then
- cti_report "Zone ${zonename} is online".
- break
- fi
- ${SLEEP} 5
- if (( !blocking_loop )); then
- timeout=$(( timeout - 5 ))
- if (( timeout < 0 )); then
- cti_report "Fully booted zone test timed out."
- debug "${fn}: exited (1)."
- return 1
- fi
- fi
- done
- debug "${fn}: exited (0)."
- return 0
- }
- #
- # NAME
- # get_zone_status
- #
- # ARGUMENTS
- # arg1 zonename
- #
- # DESCRIPTION
- # Prints the current state of the zone and returns 0; nothis is prited out
- # along with returning 1 in case the zone doesn't exist (zone is not
- # configured / installed / ..). See zoneadm(1M) list for all the known
- # states returned by the function.
- function get_zone_status
- {
- typeset -r fn=get_zone_status
- debug "${fn}: entered."
- if (( $# != 1 )); then
- cti_report "${fn}: bad amount of args ($#)"
- debug "${fn}: exited (1)."
- return 1
- fi
- is_global
- if (( $? != 0 )); then
- cti_report "Cannot be executed from the local zone."
- debug "${fn}: Incorrectly executed from the local zone."
- debug "${fn}: exited (1)."
- return 1
- fi
- typeset -r zonename="${1}"
- typeset zonestate=
- typeset sysconfig_state=
- debug "${fn}: zonename=${zonename}"
- zonestate="$(${ZONEADM} list -pc | \
- ${NAWK} -F\: '$2 ~ /'"${zonename}"'/ { print $3 }')"
-
- if [[ -z "${zonestate}" ]]; then
- debug "${fn}: Zone ${zonename} not configured."
- debug "${fn}: exited (1)."
- return 1
- fi
-
- print -n "${zonestate}"
- debug "${fn}: exited (0)."
- return 1
- }