diff --git a/monitor-snapshot/release-8.1/ansible-monitor.tar.gz b/monitor-snapshot/release-8.1/ansible-monitor.tar.gz index 2d09ba50..62192a36 100644 Binary files a/monitor-snapshot/release-8.1/ansible-monitor.tar.gz and b/monitor-snapshot/release-8.1/ansible-monitor.tar.gz differ diff --git a/monitor-snapshot/release-8.1/operator/Dockerfile b/monitor-snapshot/release-8.1/operator/Dockerfile index 08314550..29ebf702 100755 --- a/monitor-snapshot/release-8.1/operator/Dockerfile +++ b/monitor-snapshot/release-8.1/operator/Dockerfile @@ -3,6 +3,7 @@ FROM busybox:1.37.0 # Add user and group to support run it with non-root. ARG PINGCAP_UID=1000 ARG PINGCAP_GID=2000 +ENV RELOADER_UID=${PINGCAP_UID} RUN addgroup -g ${PINGCAP_GID} pingcap && \ adduser -u ${PINGCAP_UID} -G pingcap -h /home/pingcap -D pingcap diff --git a/monitor-snapshot/release-8.1/operator/datasources/k8s-datasource.yaml b/monitor-snapshot/release-8.1/operator/datasources/k8s-datasource.yaml index 9b8f9694..ea99ca8f 100755 --- a/monitor-snapshot/release-8.1/operator/datasources/k8s-datasource.yaml +++ b/monitor-snapshot/release-8.1/operator/datasources/k8s-datasource.yaml @@ -1,7 +1,7 @@ apiVersion: 1 datasources: - access: proxy - editable: true + editable: false name: k8s-cluster orgId: 1 type: prometheus diff --git a/monitor-snapshot/release-8.1/operator/init.sh b/monitor-snapshot/release-8.1/operator/init.sh index a9774e9f..a166ca4c 100755 --- a/monitor-snapshot/release-8.1/operator/init.sh +++ b/monitor-snapshot/release-8.1/operator/init.sh @@ -6,6 +6,123 @@ replace_template() { sed -i "s|$1|$replacement|g" -- "$3" } +# Reject symlink ancestors before any rule deletion, copy or ownership changes. +validate_rule_path() { + case "$1" in + /*) ;; + *) echo "Rules path must be absolute: $1" >&2; return 1;; + esac + case "/$1/" in + */../*) echo "Rules path must not contain ..: $1" >&2; return 1;; + esac + checked_path=$1 + while [ "$checked_path" != / ]; do + if [ -L "$checked_path" ]; then + echo "Rules path must not contain symlinks: $1" >&2; return 1 + fi + checked_path=${checked_path%/*} + [ -n "$checked_path" ] || checked_path=/ + done +} + +validate_rule_file() { + if [ -L "$1" ] || [ ! -f "$1" ] || [ -z "$(find "$1" -prune -type f -links 1 -print)" ]; then + echo "Rule must be a regular file with one link: $1" >&2 + return 1 + fi +} + +# Run after copying/restoring rules on every Pod initialization. Do not chown /data. +prepare_reloader_rules() { + reloader_uid=${RELOADER_UID:-1000} + initializer_uid=$(id -u) || return 1 + for reloader_id in "$reloader_uid"; do + case "$reloader_id" in + ''|*[!0-9]*) echo "Reloader UID must be numeric" >&2; return 1;; + esac + done + reloader_version=$1 + reloader_store= + set -- "$PROM_CONFIG_PATH/rules" + if [ -n "$PROM_PERSISTENT_DIR" ]; then + case "$reloader_version" in + ''|.|..|*/*) echo "Invalid persistent rules version" >&2; return 1;; + esac + reloader_store="$PROM_PERSISTENT_DIR/latest-rules/$reloader_version" + set -- "$@" "$PROM_PERSISTENT_DIR/latest-rules" "$reloader_store" + fi + for reloader_dir do + if [ -L "$reloader_dir" ] || { [ -e "$reloader_dir" ] && [ ! -d "$reloader_dir" ]; }; then + echo "Rules path must be a directory, not a symlink: $reloader_dir" >&2 + return 1 + fi + mkdir -p -- "$reloader_dir" || return 1 + if [ "$initializer_uid" = 0 ]; then + chown "$reloader_uid" "$reloader_dir" || return 1 + fi + if [ "$initializer_uid" = 0 ]; then + # Preserve the volume group and inherit it on atomic replacements. + chmod u+rwx,g+s,o-w "$reloader_dir" || return 1 + fi + done + for reloader_dir in "$PROM_CONFIG_PATH/rules" "$reloader_store"; do + [ -n "$reloader_dir" ] || continue + for reloader_file in "$reloader_dir"/*.yml "$reloader_dir"/.*.yml "$reloader_dir"/.yml; do + [ -e "$reloader_file" ] || [ -L "$reloader_file" ] || continue + validate_rule_file "$reloader_file" || return 1 + if [ "$initializer_uid" = 0 ]; then + chown "$reloader_uid" "$reloader_file" || return 1 + fi + if [ "$initializer_uid" = 0 ]; then + chmod u+rw,go-w,a-x "$reloader_file" || return 1 + fi + done + done +} + +# Restore current-version customizations automatically, as before. Validate the +# filesystem entries rather than treating all historical user edits as untrusted. +ensure_rules_directory() { + rules_dir="$PROM_CONFIG_PATH/rules" + if [ -L "$rules_dir" ] || { [ -e "$rules_dir" ] && [ ! -d "$rules_dir" ]; }; then + echo "Rules path must be a directory" >&2; return 1 + fi + mkdir -p -- "$rules_dir" || return 1 +} + +reset_rules() { + ensure_rules_directory || return 1 + for entry in "$rules_dir"/* "$rules_dir"/.[!.]* "$rules_dir"/..?*; do + [ -e "$entry" ] || [ -L "$entry" ] || continue + rm -rf -- "$entry" || return 1 + done +} + +restore_rules() { + [ -n "$PROM_PERSISTENT_DIR" ] || return 0 + case "$1" in + ''|.|..|*/*) echo "Invalid persisted rules version" >&2; return 1;; + esac + saved_root="$PROM_PERSISTENT_DIR/latest-rules" + saved_version="$saved_root/$1" + if [ -L "$PROM_PERSISTENT_DIR" ] || [ -L "$saved_root" ] || [ -L "$saved_version" ]; then + echo "Persisted rule directories must not be symbolic links" >&2; return 1 + fi + if [ -e "$saved_version" ] && [ ! -d "$saved_version" ]; then + echo "Persisted rules path must be a directory" >&2; return 1 + fi + [ -d "$saved_version" ] || return 0 + for rule in "$saved_version"/*.rules.yml "$saved_version"/.rules.yml "$saved_version"/.*.rules.yml; do + [ -e "$rule" ] || [ -L "$rule" ] || continue + validate_rule_file "$rule" || return 1 + destination="$PROM_CONFIG_PATH/rules/${rule##*/}" + if [ -e "$destination" ] || [ -L "$destination" ]; then + validate_rule_file "$destination" || return 1 + fi + cp -f -- "$rule" "$PROM_CONFIG_PATH/rules/${rule##*/}" || return 1 + done +} + # Multiline replacements would become new sed commands or malformed configuration. for value in "$DM_CLUSTER_NAME" "$TIDB_CLUSTER_NAME" "$TIDB_CLUSTER_NAMESPACE" \ "$GF_DM_PROMETHEUS_URL" "$GF_K8S_PROMETHEUS_URL" "$GF_TIDB_PROMETHEUS_URL"; do @@ -19,6 +136,11 @@ if [ -z "$GF_PROVISIONING_PATH" ] || [ -z "$PROM_CONFIG_PATH" ]; then exit 1 fi +validate_rule_path "$PROM_CONFIG_PATH/rules" || exit 1 +if [ -n "$PROM_PERSISTENT_DIR" ]; then + validate_rule_path "$PROM_PERSISTENT_DIR/latest-rules" || exit 1 +fi + if [ -n "$DM_CLUSTER_NAME" ]; then echo "running for DM" if [ ! -d "$GF_PROVISIONING_PATH/dashboards" ]; then @@ -33,9 +155,11 @@ if [ -n "$DM_CLUSTER_NAME" ]; then cp -f -- /tmp/DM-Monitor-Professional.json "$GF_PROVISIONING_PATH/dashboards" replace_template 'Test-Cluster-DM' "${DM_CLUSTER_NAME}-DM-Professional" "$GF_PROVISIONING_PATH/dashboards"/DM-Monitor-Professional.json - # Rules - if [ ! -d "$PROM_CONFIG_PATH/rules" ]; then - mkdir -p -- "$PROM_CONFIG_PATH/rules" + # Operator runs DM after TiDB against the same directory. Keep TiDB rules. + ensure_rules_directory || exit 1 + dm_rule="$PROM_CONFIG_PATH/rules/dm_worker.rules.yml" + if [ -e "$dm_rule" ] || [ -L "$dm_rule" ]; then + validate_rule_file "$dm_rule" || exit 1 fi echo $META_TYPE @@ -47,12 +171,7 @@ if [ -n "$DM_CLUSTER_NAME" ]; then fi replace_template 'ENV_LABELS_ENV' "${DM_CLUSTER_NAME}" "$PROM_CONFIG_PATH/rules/dm_worker.rules.yml" || exit 1 - # Copy Persistent rules to override raw files - if [ -n "$PROM_PERSISTENT_DIR" ]; then - if [ -d "$PROM_PERSISTENT_DIR/latest-rules/${DM_VERSION##*/}" ]; then - cp -f -- "$PROM_PERSISTENT_DIR/latest-rules/${DM_VERSION##*/}"/dm_worker.rules.yml "$PROM_CONFIG_PATH/rules" - fi - fi + restore_rules "${DM_VERSION##*/}" || exit 1 # Data sources if [ -n "$GF_DATASOURCE_PATH" ]; then @@ -61,6 +180,7 @@ if [ -n "$DM_CLUSTER_NAME" ]; then fi cp -f -- /tmp/dm-cluster-datasource.yaml "$GF_DATASOURCE_PATH/" fi + prepare_reloader_rules "${DM_VERSION##*/}" || exit 1 echo "running for DM done" exit fi @@ -161,29 +281,22 @@ for f in "$GF_PROVISIONING_PATH/dashboards"/*.json; do done # Rules -if [ ! -d "$PROM_CONFIG_PATH/rules" ]; then - mkdir -p -- "$PROM_CONFIG_PATH/rules" -else - rm -rf -- "$PROM_CONFIG_PATH/rules"/* -fi +reset_rules || exit 1 echo $META_TYPE echo $META_INSTANCE echo $META_VALUE -cp -- /tmp/*.rules.yml "$PROM_CONFIG_PATH/rules" +cp -- /tmp/*.rules.yml "$PROM_CONFIG_PATH/rules" || exit 1 for file in "$PROM_CONFIG_PATH/rules"/*; do sed -i 's/ENV_LABELS_ENV/Cluster/g' "$file" sed -i 's%job=%component=%g' "$file" sed -i -e 's%\(by\s(\)job\(,.*)\)%\1component\2%g' -e 's%\(by\s(.*\),job,\(.*)\)%\1,component,\2%g' -e 's%\(by\s(.*,\)job)%\1component)%g' -e 's%\(by\s(\)job)%\1component)%g' "$file" done -# Copy Persistent rules to override raw files -if [ -n "$PROM_PERSISTENT_DIR" ]; then - if [ -d "$PROM_PERSISTENT_DIR/latest-rules/${TIDB_VERSION##*/}" ]; then - cp -f -- "$PROM_PERSISTENT_DIR/latest-rules/${TIDB_VERSION##*/}"/*.rules.yml "$PROM_CONFIG_PATH/rules" - fi -fi +restore_rules "${TIDB_VERSION##*/}" || exit 1 # Datasources +prepare_reloader_rules "${TIDB_VERSION##*/}" || exit 1 + if [ -n "$GF_DATASOURCE_PATH" ]; then if [ -n "$GF_K8S_PROMETHEUS_URL" ]; then replace_template 'http://prometheus-k8s.monitoring.svc:9090' "${GF_K8S_PROMETHEUS_URL}" /tmp/k8s-datasource.yaml