import mysql.connector
import json
import yaml
# docker-compose.ymlファイルのパス
docker_compose_file = '/etc/kcm-setup/docker-compose.yml'
# docker-compose.ymlからデータベースの認証情報を抽出する関数
def get_db_config_from_compose():
with open(docker_compose_file, 'r') as file:
# docker-composeのYAMLファイルを読み込む
compose_data = yaml.safe_load(file)
# 'db'サービスから必要な情報を抽出
db_service = compose_data['services']['db']
environment = db_service['environment']
db_name = environment.get('GUACAMOLE_DATABASE', 'guacamole_db')
db_user = environment.get('GUACAMOLE_USERNAME', 'guacamole_user')
db_password = environment.get('GUACAMOLE_PASSWORD', 'password') # 存在しない場合に備えたデフォルト値
return {
'host': 'localhost', # Docker内で動作するため、データベースはローカルにある前提
'user': db_user,
'password': db_password,
'database': db_name,
'port': 3306 # MySQLのデフォルトポート
}
def build_connection_group_paths(cursor):
"""
親子関係を解決して、グループIDからフルパスへのマッピング辞書を作成します。
"""
cursor.execute("SELECT connection_group_id, parent_id, connection_group_name FROM guacamole_connection_group")
groups = cursor.fetchall()
group_paths = {}
def resolve_path(group_id):
if group_id is None:
return "ROOT"
if group_id in group_paths:
return group_paths[group_id]
# グループの詳細を取得
group = next(g for g in groups if g['connection_group_id'] == group_id)
parent_path = resolve_path(group['parent_id'])
full_path = f"{parent_path}/{group['connection_group_name']}"
group_paths[group_id] = full_path
return full_path
# すべてのグループのパスを解決
for group in groups:
resolve_path(group['connection_group_id'])
return group_paths
# すべての接続、ユーザー、グループ、属性を取得するSQLクエリ
query = """
SELECT
c.connection_id,
c.connection_name AS name,
c.protocol,
cp.parameter_name,
cp.parameter_value,
e.name AS entity_name,
e.type AS entity_type,
g.connection_group_id,
g.parent_id,
g.connection_group_name AS group_name,
ca.attribute_name,
ca.attribute_value
FROM
guacamole_connection c
LEFT JOIN
guacamole_connection_parameter cp ON c.connection_id = cp.connection_id
LEFT JOIN
guacamole_connection_attribute ca ON c.connection_id = ca.connection_id
LEFT JOIN
guacamole_connection_group g ON c.parent_id = g.connection_group_id
LEFT JOIN
guacamole_connection_permission p ON c.connection_id = p.connection_id
LEFT JOIN
guacamole_entity e ON p.entity_id = e.entity_id;
"""
def export_to_json(db_config):
try:
# データベースに接続
conn = mysql.connector.connect(**db_config)
cursor = conn.cursor(dictionary=True) # 扱いやすいように辞書形式のカーソルを使用
# 接続グループのパスを作成
connection_group_paths = build_connection_group_paths(cursor)
# クエリを実行
cursor.execute(query)
rows = cursor.fetchall()
# データを想定の形式に整理
connections = {}
for row in rows:
conn_id = row['connection_id']
if conn_id not in connections:
# 接続グループのパスを解決
group_path = connection_group_paths.get(row['connection_group_id'], "ROOT")
connections[conn_id] = {
'name': row['name'],
'protocol': row['protocol'],
'parameters': {},
'users': [],
'groups': [], # ここにユーザーグループが入ります
'group': group_path, # 接続グループのパス
'attributes': {}
}
# パラメータを処理
if row['parameter_name']:
connections[conn_id]['parameters'][row['parameter_name']] = row['parameter_value']
# ユーザーを処理
if row['entity_type'] == 'USER' and row['entity_name'] not in connections[conn_id]['users']:
connections[conn_id]['users'].append(row['entity_name'])
# ユーザーグループを処理
if row['entity_type'] == 'USER_GROUP' and row['entity_name'] not in connections[conn_id]['groups']:
connections[conn_id]['groups'].append(row['entity_name'])
# 属性を処理
if row['attribute_name']:
connections[conn_id]['attributes'][row['attribute_name']] = row['attribute_value']
# リスト形式に変換
connection_list = [conn for conn in connections.values()]
# JSONファイルとして出力
with open('export.json', 'w') as json_file:
json.dump(connection_list, json_file, indent=4)
print("Export successful! Data written to export.json")
except mysql.connector.Error as err:
print(f"Error: {err}")
finally:
# カーソルと接続を閉じる
if cursor:
cursor.close()
if conn:
conn.close()
if __name__ == '__main__':
# docker-compose.ymlからデータベース設定を取得
db_config = get_db_config_from_compose()
export_to_json(db_config)
import psycopg2
import psycopg2.extras
import json
import yaml
# docker-compose.ymlファイルのパス
docker_compose_file = '/etc/kcm-setup/docker-compose.yml'
# docker-compose.ymlからデータベースの認証情報を抽出する関数
def get_db_config_from_compose():
with open(docker_compose_file, 'r') as file:
compose_data = yaml.safe_load(file)
db_service = compose_data['services']['db']
env = db_service['environment']
return {
'host': 'localhost',
'user': env.get('GUACAMOLE_USERNAME', 'guacamole_user'),
'password': env.get('GUACAMOLE_PASSWORD', 'password'),
'database': env.get('GUACAMOLE_DATABASE', 'guacamole_db'),
'port': 5432 # PostgreSQLのデフォルトポート
}
def build_connection_group_paths(cursor):
cursor.execute("SELECT connection_group_id, parent_id, connection_group_name FROM guacamole_connection_group")
groups = cursor.fetchall()
group_paths = {}
def resolve_path(group_id):
if group_id is None:
return "ROOT"
if group_id in group_paths:
return group_paths[group_id]
group = next(g for g in groups if g['connection_group_id'] == group_id)
parent_path = resolve_path(group['parent_id'])
full_path = f"{parent_path}/{group['connection_group_name']}"
group_paths[group_id] = full_path
return full_path
for group in groups:
resolve_path(group['connection_group_id'])
return group_paths
# SQLクエリは同じ(PostgreSQL互換の構文)
query = """
SELECT
c.connection_id,
c.connection_name AS name,
c.protocol,
cp.parameter_name,
cp.parameter_value,
e.name AS entity_name,
e.type AS entity_type,
g.connection_group_id,
g.parent_id,
g.connection_group_name AS group_name,
ca.attribute_name,
ca.attribute_value
FROM
guacamole_connection c
LEFT JOIN
guacamole_connection_parameter cp ON c.connection_id = cp.connection_id
LEFT JOIN
guacamole_connection_attribute ca ON c.connection_id = ca.connection_id
LEFT JOIN
guacamole_connection_group g ON c.parent_id = g.connection_group_id
LEFT JOIN
guacamole_connection_permission p ON c.connection_id = p.connection_id
LEFT JOIN
guacamole_entity e ON p.entity_id = e.entity_id;
"""
def export_to_json(db_config):
try:
conn = psycopg2.connect(
host=db_config['host'],
user=db_config['user'],
password=db_config['password'],
dbname=db_config['database'],
port=db_config['port']
)
cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
connection_group_paths = build_connection_group_paths(cursor)
cursor.execute(query)
real_dict_rows = cursor.fetchall()
# RealDictRowオブジェクトを通常のdictに変換
rows = [dict(row) for row in real_dict_rows]
# データを想定の形式に整理
connections = {}
for row in rows:
conn_id = row['connection_id']
if conn_id not in connections:
group_path = connection_group_paths.get(row['connection_group_id'], "ROOT")
connections[conn_id] = {
'name': row['name'],
'protocol': row['protocol'],
'parameters': {},
'users': [],
'groups': [],
'group': group_path,
'attributes': {}
}
if row['parameter_name']:
connections[conn_id]['parameters'][row['parameter_name']] = row['parameter_value']
if row['entity_type'] == 'USER' and row['entity_name'] not in connections[conn_id]['users']:
connections[conn_id]['users'].append(row['entity_name'])
if row['entity_type'] == 'USER_GROUP' and row['entity_name'] not in connections[conn_id]['groups']:
connections[conn_id]['groups'].append(row['entity_name'])
if row['attribute_name']:
connections[conn_id]['attributes'][row['attribute_name']] = row['attribute_value']
with open('export.json', 'w') as json_file:
json.dump(list(connections.values()), json_file, indent=4)
print("Export successful! Data written to export.json")
except psycopg2.Error as err:
print(f"Database Error: {err}")
finally:
# カーソルと接続を閉じる
if cursor:
cursor.close()
if conn:
conn.close()
if __name__ == '__main__':
db_config = get_db_config_from_compose()
export_to_json(db_config)