89 lines
3.2 KiB
Python
Executable File
89 lines
3.2 KiB
Python
Executable File
#!/usr/bin/env python
|
|
#
|
|
# Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
#
|
|
""" Secure the MySQL installation (/usr/bin/mysql_secure_installation) """
|
|
|
|
import json
|
|
import logging
|
|
import os
|
|
import shutil
|
|
|
|
import MySQLdb
|
|
|
|
logging.basicConfig()
|
|
logger = logging.getLogger('mysql-secure')
|
|
|
|
|
|
# TODO(therese-mchale) Refactor to use a common
|
|
# load_userfile for this and 50-mysql-users
|
|
def load_userfile(path, users):
|
|
if os.path.exists(path):
|
|
with open(path) as dbusers_file:
|
|
db_users = json.load(dbusers_file)
|
|
if not isinstance(db_users, list):
|
|
raise ValueError('%s must be a list' % (path))
|
|
for dbvalues in db_users:
|
|
username = dbvalues['username']
|
|
users[username] = dbvalues
|
|
|
|
|
|
def secure_installation(rootuser):
|
|
# Try to connect with no password, ~/.my.cnf and
|
|
# /mnt/state/root/metadata.my.cnf in that order.
|
|
# This should cover os-refresh-config post install
|
|
# and re-image
|
|
try:
|
|
conn = MySQLdb.Connect()
|
|
except Exception:
|
|
try:
|
|
conn = MySQLdb.Connect(
|
|
read_default_file=os.path.expanduser('~/.my.cnf'))
|
|
except Exception:
|
|
conn = MySQLdb.Connect(
|
|
read_default_file='/mnt/state/root/metadata.my.cnf')
|
|
with conn:
|
|
# Remove Anonymous Users
|
|
cursor = conn.cursor()
|
|
cursor.execute("DELETE FROM mysql.user WHERE User = %s", "")
|
|
# Remove remote root access
|
|
cursor.execute("DELETE FROM mysql.user WHERE User = %s "
|
|
"AND Host NOT IN (%s, %s, %s)",
|
|
("root", "localhost", "127.0.0.1", "::1"))
|
|
# Remove the test database
|
|
cursor.execute("DROP DATABASE IF EXISTS test")
|
|
cursor.execute("DELETE FROM mysql.db WHERE Db=%s OR Db=%s",
|
|
("test", "test\\_%"))
|
|
# Make sure the root password for ALL root accounts
|
|
# (i.e. 'localhost', '127.0.0.1', '::1' included) is set correctly
|
|
if 'password' in rootuser:
|
|
rootpwd = rootuser['password']
|
|
cmd = ("UPDATE mysql.user SET Password=PASSWORD("
|
|
"%s) WHERE User=%s")
|
|
cursor.execute(cmd, (rootpwd, "root"))
|
|
cursor.execute("FLUSH PRIVILEGES")
|
|
# As Above also sets root password .my.cnf with new password
|
|
shutil.copy2('/mnt/state/root/metadata.my.cnf',
|
|
os.path.expanduser('~/.my.cnf'))
|
|
cursor.close()
|
|
|
|
users = {}
|
|
load_userfile('/etc/mysql/static-dbusers.json', users)
|
|
load_userfile('/etc/mysql/dbusers.json', users)
|
|
|
|
rootuser = users['root']
|
|
secure_installation(rootuser)
|