Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
13 changes: 11 additions & 2 deletions cf_remote/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
transfer_file,
deploy_masterfiles,
)
import cf_remote.demo as demo_lib
from cf_remote.packages import Releases
from cf_remote.web import download_package
from cf_remote.paths import (
Expand Down Expand Up @@ -229,12 +230,18 @@ def install(
"\n".join(bootstrap + [""]),
)

hub_passwords = {}
hub_jobs = []
if hubs:
show_host_info = len(hubs) == 1
if type(hubs) is str:
hubs = [hubs]
for index, hub in enumerate(hubs):
if demo:
password, salt, sha = demo_lib.generate_password()
hub_passwords[hub] = password
else:
salt, sha = None, None
hub_jobs.append(
HostInstaller(
hub,
Expand All @@ -249,6 +256,8 @@ def install(
remote_download=remote_download,
trust_keys=trust_keys,
insecure=insecure,
demo_salt=salt,
demo_sha=sha,
)
)

Expand Down Expand Up @@ -293,8 +302,8 @@ def install(
if demo and hubs:
for hub in hubs:
print(
"Your demo hub is ready: https://{}/ (Username: admin, Password: password)".format(
strip_user(hub)
"Your demo hub is ready: https://{}/ (Username: admin, Password: {})".format(
strip_user(hub), hub_passwords[hub]
)
)

Expand Down
52 changes: 43 additions & 9 deletions cf_remote/demo.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import os
import json
import hashlib
import secrets
import shutil
import string
import tempfile
from posixpath import dirname, join

from cf_remote import log
Expand All @@ -22,18 +27,47 @@ def agent_run(data, *, connection=None):
log.debug(output)


def generate_password():
"""Generate credentials for the demo admin user.

Returns (password, salt, sha) where sha is the hex SHA-256 of
salt + password concatenated with no separator. The password is meant
to be shown to the user; only the salt and sha are sent to the host.
"""
password = "".join(secrets.choice(string.ascii_letters) for _ in range(14))
salt = "".join(secrets.choice(string.ascii_letters) for _ in range(10))
sha = hashlib.sha256((salt + password).encode("utf-8")).hexdigest()
return password, salt, sha


@auto_connect
def disable_password_dialog(host, *, connection=None):
print("Disabling password change on hub: '{}'".format(host))
def setup_demo_admin_user(host, salt, sha, *, connection=None):
print("Setting up demo admin user on hub: '{}'".format(host))

query_path = join(dirname(__file__), "demo.sql")
scp(query_path, host, connection=connection)
template_path = join(dirname(__file__), "demo.sql")
with open(template_path, "r") as f:
sql = f.read()
sql = sql.replace("__CF_REMOTE_SHA__", sha).replace("__CF_REMOTE_SALT__", salt)

query = os.path.basename(query_path)
ssh_sudo(
connection,
'/var/cfengine/bin/psql cfsettings -f "{}"'.format(query),
)
# The SQL file contains the password salt and SHA. mkdtemp creates the
# directory with 0700 perms, so anything inside is protected from other
# local users.
tmp_dir = tempfile.mkdtemp(prefix="cf-remote-demo-")
try:
rendered_path = os.path.join(tmp_dir, "demo.sql")
with open(rendered_path, "w") as f:
f.write(sql)
scp(rendered_path, host, connection=connection)
query = os.path.basename(rendered_path)
try:
ssh_sudo(
connection,
'/var/cfengine/bin/psql cfsettings -f "{}"'.format(query),
)
finally:
ssh_cmd(connection, 'rm -f "{}"'.format(query))
finally:
shutil.rmtree(tmp_dir, ignore_errors=True)


def def_json(call_collect=False):
Expand Down
8 changes: 4 additions & 4 deletions cf_remote/demo.sql
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ INSERT INTO "users" ("username",
"roles",
"changetimestamp")
SELECT 'admin',
'SHA=7f062dc2ef82d2b87f012fc17d70c372aa4e2883d9b6c5c1cc7382a5c868b724',
'eWAbKQmxNP',
'SHA=__CF_REMOTE_SHA__',
'__CF_REMOTE_SALT__',
'admin',
'admin@organisation.com',
FALSE,
Expand All @@ -23,5 +23,5 @@ SELECT 'admin',
now() ON CONFLICT (username,
EXTERNAL) DO
UPDATE
SET password = 'SHA=7f062dc2ef82d2b87f012fc17d70c372aa4e2883d9b6c5c1cc7382a5c868b724',
salt = 'eWAbKQmxNP';
SET password = 'SHA=__CF_REMOTE_SHA__',
salt = '__CF_REMOTE_SALT__';
8 changes: 6 additions & 2 deletions cf_remote/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,9 @@ def install_host(
show_info=True,
remote_download=False,
trust_keys=None,
insecure=False
insecure=False,
demo_salt=None,
demo_sha=None,
):
data = get_info(host, connection=connection)
if show_info:
Expand Down Expand Up @@ -758,7 +760,9 @@ def install_host(
host, connection=connection, call_collect=call_collect
)
demo_lib.agent_run(data, connection=connection)
demo_lib.disable_password_dialog(host, connection=connection)
demo_lib.setup_demo_admin_user(
host, demo_salt, demo_sha, connection=connection
)
demo_lib.agent_run(data, connection=connection)
return 0

Expand Down
Loading