Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Combine deploy enhancements #1694

Merged
merged 10 commits into from
Jul 20, 2022
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions deploy/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ RUN pip3 install -r ${HOME}/requirements.txt

RUN mkdir ${HOME}/.ssh

# Copy configuration management scripts
COPY docker_home/* ${HOME}/

# Copy Python scripts for setting up and deploying the target
# to ~/scripts
COPY scripts/ ${HOME}/scripts
Expand Down
107 changes: 107 additions & 0 deletions deploy/docker_home/.bashrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

# Save the configuration on exit
trap_exit() {
. "$HOME/save_config.sh"
}
trap trap_exit EXIT

# don't put duplicate lines in the history. See bash(1) for more options
# ... or force ignoredups and ignorespace
HISTCONTROL=ignoredups:ignorespace

# append to the history file, don't overwrite it
shopt -s histappend

# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000

# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize

# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"

# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then
debian_chroot=$(cat /etc/debian_chroot)
fi

# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
xterm-color) color_prompt=yes;;
esac

# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
#force_color_prompt=yes

if [ -n "$force_color_prompt" ]; then
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
# We have color support; assume it's compliant with Ecma-48
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
# a case would tend to support setf rather than setaf.)
color_prompt=yes
else
color_prompt=
fi
fi

if [ "$color_prompt" = yes ]; then
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt

# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
;;
*)
;;
esac

# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
alias ls='ls --color=auto'
#alias dir='dir --color=auto'
#alias vdir='vdir --color=auto'

alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
fi

# some more ls aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'

# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.

if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fi

# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
#if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
# . /etc/bash_completion
#fi

. "$HOME/restore_config.sh"
12 changes: 12 additions & 0 deletions deploy/docker_home/restore_config.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# restore /etc/hosts entries for combine targets
if [ -f "/config/hosts" ] ; then
cp /config/hosts /etc/hosts
fi

if [ -d "/config/.ssh" ] ; then
cp -r /config/.ssh ${HOME}
fi

if [ -d "/config/.kube" ] ; then
cp -r /config/.kube ${HOME}
fi
11 changes: 11 additions & 0 deletions deploy/docker_home/save_config.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# ~/.bash_logout: executed by bash login shells on exit.

if [ -d "/config" ] ; then
cp /etc/hosts /config
if [ -d "${HOME}/.ssh" ] ; then
cp -r ${HOME}/.ssh /config
fi
if [ -d "${HOME}/.kube" ] ; then
cp -r ${HOME}/.kube /config
fi
fi
82 changes: 82 additions & 0 deletions deploy/scripts/check_certs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#! /usr/bin/env python3

import argparse
import subprocess
from typing import List, Optional

from utils import run_cmd


def parse_args() -> argparse.Namespace:
"""Define command line arguments for parser."""
parser = argparse.ArgumentParser(
description="Print the expiration date for each certificate installed on the target.",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
parser.add_argument("--namespace", "-n", help="Namespace to check for TLS secrets.")
return parser.parse_args()


def get_expiration(secret: str, kubectl_opts: List[str]) -> Optional[str]:
if not secret:
return None
get_secret = subprocess.Popen(
["kubectl"]
+ kubectl_opts
+ [
"get",
secret,
"-o",
r"jsonpath={.data['tls\.crt']}",
],
stdout=subprocess.PIPE,
text=True,
)
decode = subprocess.Popen(
["base64", "-d"],
stdin=get_secret.stdout,
stdout=subprocess.PIPE,
text=True,
)
if get_secret.stdout is not None:
get_secret.stdout.close()
enddate = subprocess.Popen(
[
"openssl",
"x509",
"-enddate",
"-noout",
],
stdin=decode.stdout,
stdout=subprocess.PIPE,
text=True,
)
if decode.stdout is not None:
decode.stdout.close()
expiration = enddate.communicate()[0]
expiration = expiration.replace("notAfter=", "").strip()
return expiration


def main() -> None:
"""Setup access to the the target specified on the command line."""
args = parse_args()

if args.namespace is not None:
kubectl_opts = ["-n", args.namespace]
else:
kubectl_opts = []

secrets_list = run_cmd(
["kubectl"]
+ kubectl_opts
+ ["get", "secrets", "--field-selector", "type=kubernetes.io/tls", "-o", "name"]
)

for secret in secrets_list.stdout.split("\n"):
if secret:
print(f"{secret} expires on {get_expiration(secret, kubectl_opts)}")


if __name__ == "__main__":
main()
6 changes: 4 additions & 2 deletions deploy/scripts/setup_target.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def parse_args() -> argparse.Namespace:


def update_hosts_file(tgt_ip: str, tgt_name: str, hosts_filename: Path) -> None:
"""Map tgt_name to tgt_ip in the specified hosts_filename."""
match = re.search(r"^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\..(\d{1,3})$", tgt_ip)
if match is not None:
ip_pattern = tgt_ip.replace(".", r"\.")
Expand Down Expand Up @@ -52,13 +53,13 @@ def update_hosts_file(tgt_ip: str, tgt_name: str, hosts_filename: Path) -> None:
output_line = f"{line} {tgt_name}"
entry_found = True
elif name_in_line.search(line):
# replace IP address for args.name an any other hosts with that IP address
# replace IP address for args.name and any other hosts with that IP address
output_line = re.sub(r"^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\..(\d{1,3})", tgt_ip, line)
entry_found = True
else:
output_line = f"{line}"

output_file.write(f"{output_line}\n")

if not entry_found:
output_file.write(f"{tgt_ip} {tgt_name}\n")
hosts_file.close()
Expand All @@ -67,6 +68,7 @@ def update_hosts_file(tgt_ip: str, tgt_name: str, hosts_filename: Path) -> None:


def main() -> None:
"""Setup access to the the target specified on the command line."""
args = parse_args()
# Add the target IP and target name to /etc/hosts (or other hosts file)
update_hosts_file(args.ip, args.name, Path(args.hosts).resolve())
Expand Down
2 changes: 1 addition & 1 deletion deploy/scripts/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def run_cmd(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True,
text=True,
check=check_results,
)
if print_output:
Expand Down