feat(auth): Enhance authentication management with yq support for YAML parsing
Some checks failed
/ validate-docker-compose (push) Has been cancelled
Some checks failed
/ validate-docker-compose (push) Has been cancelled
This commit is contained in:
parent
a74707dc1f
commit
f4409eb258
198
update-setup.sh
198
update-setup.sh
@ -31,6 +31,16 @@ AUTHELIA_CONFIG_BACKUP="authelia/configuration.${TIMESTAMP}.bak"
|
|||||||
COMPOSE_FILE="docker-compose.yml"
|
COMPOSE_FILE="docker-compose.yml"
|
||||||
COMPOSE_BACKUP="docker-compose.${TIMESTAMP}.bak"
|
COMPOSE_BACKUP="docker-compose.${TIMESTAMP}.bak"
|
||||||
|
|
||||||
|
# Check if yq is installed
|
||||||
|
check_yq() {
|
||||||
|
if ! command -v yq &> /dev/null; then
|
||||||
|
echo -e "${YELLOW}Warning: 'yq' is not installed. While not required, it provides better YAML handling.${NC}"
|
||||||
|
echo -e "${YELLOW}Installation instructions: https://github.com/mikefarah/yq#install${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
# Print section header
|
# Print section header
|
||||||
print_header() {
|
print_header() {
|
||||||
echo -e "\n${CYAN}${BOLD}$1${NC}"
|
echo -e "\n${CYAN}${BOLD}$1${NC}"
|
||||||
@ -368,8 +378,24 @@ generate_passphrase() {
|
|||||||
# PART 4: Authentication Management
|
# PART 4: Authentication Management
|
||||||
##################################################
|
##################################################
|
||||||
|
|
||||||
|
# Get the current auth status for a service
|
||||||
get_auth_status() {
|
get_auth_status() {
|
||||||
local service=$1
|
local service=$1
|
||||||
|
|
||||||
|
# Use yq if available for more reliable YAML parsing
|
||||||
|
if command -v yq &> /dev/null; then
|
||||||
|
local middlewares=$(yq e ".services.$service.labels[] | select(contains(\"traefik.http.routers.$service.middlewares=\"))" "$COMPOSE_FILE" 2>/dev/null)
|
||||||
|
if [ -n "$middlewares" ]; then
|
||||||
|
if echo "$middlewares" | grep -q "authelia-auth"; then
|
||||||
|
echo "enabled"
|
||||||
|
else
|
||||||
|
echo "disabled"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "unknown"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Fall back to grep if yq isn't available
|
||||||
if grep -q "traefik.http.routers.$service.middlewares=.*authelia-auth" "$COMPOSE_FILE"; then
|
if grep -q "traefik.http.routers.$service.middlewares=.*authelia-auth" "$COMPOSE_FILE"; then
|
||||||
echo "enabled"
|
echo "enabled"
|
||||||
elif grep -q "traefik.http.routers.$service.middlewares=" "$COMPOSE_FILE"; then
|
elif grep -q "traefik.http.routers.$service.middlewares=" "$COMPOSE_FILE"; then
|
||||||
@ -377,12 +403,73 @@ get_auth_status() {
|
|||||||
else
|
else
|
||||||
echo "unknown"
|
echo "unknown"
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
enable_auth() {
|
enable_auth() {
|
||||||
local service=$1
|
local service=$1
|
||||||
echo -e "${BLUE}Enabling authentication for $service...${NC}"
|
echo -e "${BLUE}Enabling authentication for $service...${NC}"
|
||||||
|
|
||||||
|
# Check if service exists in the compose file
|
||||||
|
# Use yq if available for more reliable parsing
|
||||||
|
if command -v yq &> /dev/null; then
|
||||||
|
# Check if service exists
|
||||||
|
local service_exists=$(yq e ".services.$service" "$COMPOSE_FILE" 2>/dev/null)
|
||||||
|
if [ -z "$service_exists" ] || [ "$service_exists" == "null" ]; then
|
||||||
|
echo -e "${RED}Service $service not found in $COMPOSE_FILE${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if auth is already enabled
|
||||||
|
local middlewares=$(yq e ".services.$service.labels[] | select(contains(\"traefik.http.routers.$service.middlewares=\"))" "$COMPOSE_FILE" 2>/dev/null)
|
||||||
|
if [ -n "$middlewares" ] && echo "$middlewares" | grep -q "authelia-auth"; then
|
||||||
|
echo -e "${GREEN}Authentication already enabled for $service${NC}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create a temporary file for editing with yq
|
||||||
|
local temp_file="${COMPOSE_FILE}.tmp"
|
||||||
|
|
||||||
|
# Check if there's already a middlewares label
|
||||||
|
if [ -n "$middlewares" ]; then
|
||||||
|
# Modify the existing middlewares label to include authelia-auth
|
||||||
|
if echo "$middlewares" | grep -q "middlewares=$"; then
|
||||||
|
# Empty middlewares
|
||||||
|
yq e ".services.$service.labels |= map(. | select(contains(\"traefik.http.routers.$service.middlewares=\")) |= \"traefik.http.routers.$service.middlewares=authelia-auth@docker\" // .)" "$COMPOSE_FILE" > "$temp_file"
|
||||||
|
elif echo "$middlewares" | grep -q "middlewares=.*@docker"; then
|
||||||
|
# Has other middlewares with @docker
|
||||||
|
local current_value=$(echo "$middlewares" | sed 's/.*middlewares=\(.*\)@docker.*/\1/')
|
||||||
|
yq e ".services.$service.labels |= map(. | select(contains(\"traefik.http.routers.$service.middlewares=\")) |= \"traefik.http.routers.$service.middlewares=${current_value},authelia-auth@docker\" // .)" "$COMPOSE_FILE" > "$temp_file"
|
||||||
|
else
|
||||||
|
# Has middlewares without @docker
|
||||||
|
local current_value=$(echo "$middlewares" | sed 's/.*middlewares=\(.*\).*/\1/')
|
||||||
|
yq e ".services.$service.labels |= map(. | select(contains(\"traefik.http.routers.$service.middlewares=\")) |= \"traefik.http.routers.$service.middlewares=${current_value},authelia-auth@docker\" // .)" "$COMPOSE_FILE" > "$temp_file"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Need to add a new middlewares label
|
||||||
|
# Check if the service has any labels
|
||||||
|
local has_labels=$(yq e ".services.$service.labels" "$COMPOSE_FILE" 2>/dev/null)
|
||||||
|
if [ -z "$has_labels" ] || [ "$has_labels" == "null" ]; then
|
||||||
|
# Add a new labels array with the middlewares
|
||||||
|
yq e ".services.$service.labels = [\"traefik.http.routers.$service.middlewares=authelia-auth@docker\"]" "$COMPOSE_FILE" > "$temp_file"
|
||||||
|
else
|
||||||
|
# Add the middlewares to the existing labels
|
||||||
|
yq e ".services.$service.labels += [\"traefik.http.routers.$service.middlewares=authelia-auth@docker\"]" "$COMPOSE_FILE" > "$temp_file"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Replace the original file if the temp file was created successfully
|
||||||
|
if [ $? -eq 0 ] && [ -f "$temp_file" ]; then
|
||||||
|
mv "$temp_file" "$COMPOSE_FILE"
|
||||||
|
echo -e "${GREEN}Authentication enabled for $service${NC}"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
echo -e "${RED}Failed to update the compose file with yq. Falling back to sed.${NC}"
|
||||||
|
rm -f "$temp_file" # Clean up if the temp file exists
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fall back to the existing implementation if yq is not available or failed
|
||||||
if ! grep -q "container_name: $service" "$COMPOSE_FILE"; then
|
if ! grep -q "container_name: $service" "$COMPOSE_FILE"; then
|
||||||
echo -e "${RED}Service $service not found in $COMPOSE_FILE${NC}"
|
echo -e "${RED}Service $service not found in $COMPOSE_FILE${NC}"
|
||||||
return 1
|
return 1
|
||||||
@ -443,6 +530,63 @@ disable_auth() {
|
|||||||
local service=$1
|
local service=$1
|
||||||
echo -e "${BLUE}Disabling authentication for $service...${NC}"
|
echo -e "${BLUE}Disabling authentication for $service...${NC}"
|
||||||
|
|
||||||
|
# Use yq if available for more reliable parsing
|
||||||
|
if command -v yq &> /dev/null; then
|
||||||
|
# Check if service exists
|
||||||
|
local service_exists=$(yq e ".services.$service" "$COMPOSE_FILE" 2>/dev/null)
|
||||||
|
if [ -z "$service_exists" ] || [ "$service_exists" == "null" ]; then
|
||||||
|
echo -e "${RED}Service $service not found in $COMPOSE_FILE${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if auth is already disabled
|
||||||
|
local middlewares=$(yq e ".services.$service.labels[] | select(contains(\"traefik.http.routers.$service.middlewares=\"))" "$COMPOSE_FILE" 2>/dev/null)
|
||||||
|
if [ -n "$middlewares" ] && ! echo "$middlewares" | grep -q "authelia-auth"; then
|
||||||
|
echo -e "${GREEN}Authentication already disabled for $service${NC}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create a temporary file for editing with yq
|
||||||
|
local temp_file="${COMPOSE_FILE}.tmp"
|
||||||
|
|
||||||
|
# Extract current middlewares
|
||||||
|
if [ -n "$middlewares" ]; then
|
||||||
|
if echo "$middlewares" | grep -q "traefik.http.routers.$service.middlewares=authelia-auth@docker$"; then
|
||||||
|
# Only authelia-auth@docker, replace with empty
|
||||||
|
yq e ".services.$service.labels |= map(. | select(contains(\"traefik.http.routers.$service.middlewares=\")) |= \"traefik.http.routers.$service.middlewares=\" // .)" "$COMPOSE_FILE" > "$temp_file"
|
||||||
|
elif echo "$middlewares" | grep -q "traefik.http.routers.$service.middlewares=authelia-auth@docker,"; then
|
||||||
|
# authelia-auth@docker at start with comma
|
||||||
|
local remaining=$(echo "$middlewares" | sed 's/.*middlewares=authelia-auth@docker,\(.*\)/\1/')
|
||||||
|
yq e ".services.$service.labels |= map(. | select(contains(\"traefik.http.routers.$service.middlewares=\")) |= \"traefik.http.routers.$service.middlewares=${remaining}\" // .)" "$COMPOSE_FILE" > "$temp_file"
|
||||||
|
elif echo "$middlewares" | grep -q "traefik.http.routers.$service.middlewares=.*,authelia-auth@docker$"; then
|
||||||
|
# authelia-auth@docker at end with comma
|
||||||
|
local remaining=$(echo "$middlewares" | sed 's/\(.*\),authelia-auth@docker$/\1/')
|
||||||
|
yq e ".services.$service.labels |= map(. | select(contains(\"traefik.http.routers.$service.middlewares=\")) |= \"traefik.http.routers.$service.middlewares=${remaining}\" // .)" "$COMPOSE_FILE" > "$temp_file"
|
||||||
|
elif echo "$middlewares" | grep -q "traefik.http.routers.$service.middlewares=.*,authelia-auth@docker,.*"; then
|
||||||
|
# authelia-auth@docker in the middle with commas
|
||||||
|
local remaining=$(echo "$middlewares" | sed 's/\(.*\),authelia-auth@docker,\(.*\)/\1,\2/')
|
||||||
|
yq e ".services.$service.labels |= map(. | select(contains(\"traefik.http.routers.$service.middlewares=\")) |= \"traefik.http.routers.$service.middlewares=${remaining}\" // .)" "$COMPOSE_FILE" > "$temp_file"
|
||||||
|
else
|
||||||
|
echo -e "${RED}Could not determine how to remove authelia-auth from middlewares for $service${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Replace the original file if the temp file was created successfully
|
||||||
|
if [ $? -eq 0 ] && [ -f "$temp_file" ]; then
|
||||||
|
mv "$temp_file" "$COMPOSE_FILE"
|
||||||
|
echo -e "${GREEN}Authentication disabled for $service${NC}"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
echo -e "${RED}Failed to update the compose file with yq. Falling back to sed.${NC}"
|
||||||
|
rm -f "$temp_file" # Clean up if the temp file exists
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}No middlewares found for $service, authentication is already disabled${NC}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fall back to the existing implementation if yq is not available or failed
|
||||||
if ! grep -q "container_name: $service" "$COMPOSE_FILE"; then
|
if ! grep -q "container_name: $service" "$COMPOSE_FILE"; then
|
||||||
echo -e "${RED}Service $service not found in $COMPOSE_FILE${NC}"
|
echo -e "${RED}Service $service not found in $COMPOSE_FILE${NC}"
|
||||||
return 1
|
return 1
|
||||||
@ -473,18 +617,66 @@ disable_auth() {
|
|||||||
list_services() {
|
list_services() {
|
||||||
print_header "Services Authentication Status"
|
print_header "Services Authentication Status"
|
||||||
|
|
||||||
|
# Check if file exists
|
||||||
|
if ! check_file "$COMPOSE_FILE"; then
|
||||||
|
echo -e "${RED}Error: $COMPOSE_FILE doesn't exist${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Show a warning if we're not creating a backup for this operation
|
||||||
echo -e "${BLUE}Checking services in $COMPOSE_FILE...${NC}"
|
echo -e "${BLUE}Checking services in $COMPOSE_FILE...${NC}"
|
||||||
echo -e "${CYAN}SERVICE\t\tAUTH STATUS${NC}"
|
echo -e "${CYAN}SERVICE\t\tAUTH STATUS${NC}"
|
||||||
echo -e "${CYAN}-------\t\t-----------${NC}"
|
echo -e "${CYAN}-------\t\t-----------${NC}"
|
||||||
|
|
||||||
local services=$(grep "container_name:" "$COMPOSE_FILE" | awk '{print $3}')
|
|
||||||
local service_count=0
|
local service_count=0
|
||||||
|
|
||||||
|
# Use yq if available for more reliable parsing
|
||||||
|
if command -v yq &> /dev/null; then
|
||||||
|
# Get all services from the docker-compose.yml file
|
||||||
|
local services=$(yq e '.services | keys | .[]' "$COMPOSE_FILE" 2>/dev/null)
|
||||||
|
|
||||||
for service in $services; do
|
for service in $services; do
|
||||||
|
# Skip infrastructure containers
|
||||||
if [[ "$service" == "redis" || "$service" == "authelia" || "$service" == "traefik" || "$service" == "tailscale" || "$service" == "watchtower" || "$service" == "autoheal" || "$service" == "middlewares" ]]; then
|
if [[ "$service" == "redis" || "$service" == "authelia" || "$service" == "traefik" || "$service" == "tailscale" || "$service" == "watchtower" || "$service" == "autoheal" || "$service" == "middlewares" ]]; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Check if this service has Traefik router configured
|
||||||
|
local has_router=$(yq e ".services.$service.labels[] | select(contains(\"traefik.http.routers.$service\"))" "$COMPOSE_FILE" 2>/dev/null)
|
||||||
|
if [ -n "$has_router" ]; then
|
||||||
|
local status=$(get_auth_status "$service")
|
||||||
|
|
||||||
|
# Format the output with padding
|
||||||
|
printf "${BOLD}%-20s${NC}" "$service"
|
||||||
|
|
||||||
|
case "$status" in
|
||||||
|
"enabled")
|
||||||
|
echo -e "${GREEN}Enabled${NC}"
|
||||||
|
service_count=$((service_count + 1))
|
||||||
|
;;
|
||||||
|
"disabled")
|
||||||
|
echo -e "${YELLOW}Disabled${NC}"
|
||||||
|
service_count=$((service_count + 1))
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo -e "${RED}Unknown${NC}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
# Fallback to using grep for parsing (less reliable)
|
||||||
|
# First identify all container names
|
||||||
|
local services=$(grep "container_name:" "$COMPOSE_FILE" | awk '{print $3}')
|
||||||
|
|
||||||
|
for service in $services; do
|
||||||
|
# Skip infrastructure containers
|
||||||
|
if [[ "$service" == "redis" || "$service" == "authelia" || "$service" == "traefik" || "$service" == "tailscale" || "$service" == "watchtower" || "$service" == "autoheal" || "$service" == "middlewares" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Look specifically for router configuration for this service
|
||||||
|
if grep -q "traefik.http.routers.$service" "$COMPOSE_FILE"; then
|
||||||
local status=$(get_auth_status "$service")
|
local status=$(get_auth_status "$service")
|
||||||
|
|
||||||
printf "${BOLD}%-20s${NC}" "$service"
|
printf "${BOLD}%-20s${NC}" "$service"
|
||||||
@ -502,10 +694,14 @@ list_services() {
|
|||||||
echo -e "${RED}Unknown${NC}"
|
echo -e "${RED}Unknown${NC}"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
if [ $service_count -eq 0 ]; then
|
if [ $service_count -eq 0 ]; then
|
||||||
echo -e "${YELLOW}No services found with authentication status.${NC}"
|
echo -e "${YELLOW}No services found with authentication status.${NC}"
|
||||||
|
echo -e "${YELLOW}This could indicate that no services are configured with Traefik routers,${NC}"
|
||||||
|
echo -e "${YELLOW}or that the compose file has an unexpected structure.${NC}"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user