Skip to content

Instantly share code, notes, and snippets.

@jborean93
Created February 23, 2024 00:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jborean93/7b195b7e22fad70605a3a702e05eb205 to your computer and use it in GitHub Desktop.
Save jborean93/7b195b7e22fad70605a3a702e05eb205 to your computer and use it in GitHub Desktop.
POC for Ansible callback that calls kinit
# Copyright (c) 2024 Jordan Borean
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import annotations
DOCUMENTATION = """
name: kinit
type: aggregate
short_description: POC to run kinit on a playbook run.
description:
- Runs kinit to retrieve a Kerberos ticket for the playbook connection plugins
to use.
- This stores the Kerberos ccache as a temporary file and is automatically used
by any Kerberos C clients through the KRB5CCNAME env var.
author: Jordan Borean (@jborean93)
options:
username:
description:
- The username to retrieve the ticket for.
type: str
required: true
env:
# Allow you to override with a custom user if need be
- name: ANSIBLE_KINIT_USERNAME
# Fallback env vars used by ssh
- name: ANSIBLE_REMOTE_USER
password:
description:
- The password for the user.
type: str
required: true
env:
- name: ANSIBLE_KINIT_PASSWORD
forwardable:
description:
- Request a forwardable ticket used for delegation.
type: bool
default: false
env:
- name: ANSIBLE_KINIT_FORWARDABLE
"""
import os
import shlex
import subprocess
import tempfile
from ansible.errors import AnsibleCallbackError
from ansible.playbook import Playbook
from ansible.plugins.callback import CallbackBase
class CallbackModule(CallbackBase):
CALLBACK_VERSION = 2.0
CALLBACK_TYPE = "aggregate"
CALLBACK_NAME = "kinit"
CALLBACK_NEEDS_ENABLED = True
def __init__(self) -> None:
super().__init__()
# We need to keep a reference to the temp file so it stays available
# throughout the whole run.
self._ccache = tempfile.NamedTemporaryFile()
def v2_playbook_on_start(
self,
playbook: Playbook,
) -> None:
username = self.get_option("username")
password = self.get_option("password")
forwardable = self.get_option("forwardable")
sysname = os.uname()[0]
kinit_args = ["kinit"]
if sysname == "Darwin":
kinit_args.append("--password-file=STDIN")
if forwardable:
kinit_args.append("-f")
kinit_args.append(username)
os.environ["KRB5CCNAME"] = f"FILE:{self._ccache.name}"
process = subprocess.Popen(
kinit_args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
stdout, stderr = process.communicate(password.encode() + b"\n")
rc = process.returncode
if rc:
msg = f"Kinit [{shlex.join(kinit_args)}] failed with RC: {rc}. STDOUT: {stdout.decode()}. STDERR: {stderr.decode()}"
raise AnsibleCallbackError(msg)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment