mirror of
git://git.yoctoproject.org/layerindex-web.git
synced 2025-07-19 20:59:01 +02:00
dockersetup: use separate db account with lower privileges
Make the app should use a database account that has only the privileges it needs rather than the root account for improved security. Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
This commit is contained in:
parent
3775efc848
commit
7a248df9f5
|
@ -17,6 +17,7 @@ services:
|
||||||
- layersmeta:/opt/workdir
|
- layersmeta:/opt/workdir
|
||||||
environment:
|
environment:
|
||||||
#- "SECRET_KEY=<set this here>"
|
#- "SECRET_KEY=<set this here>"
|
||||||
|
- "DATABASE_USER=root"
|
||||||
- "DATABASE_PASSWORD=testingpw"
|
- "DATABASE_PASSWORD=testingpw"
|
||||||
- "DATABASE_HOST=layersdb"
|
- "DATABASE_HOST=layersdb"
|
||||||
- "RABBITMQ_DEFAULT_USER=guest"
|
- "RABBITMQ_DEFAULT_USER=guest"
|
||||||
|
|
|
@ -17,7 +17,7 @@ DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.mysql',
|
'ENGINE': 'django.db.backends.mysql',
|
||||||
'NAME': 'layersdb',
|
'NAME': 'layersdb',
|
||||||
'USER': 'root',
|
'USER': os.getenv('DATABASE_USER', 'root'),
|
||||||
'PASSWORD': os.getenv('DATABASE_PASSWORD', 'testingpw'),
|
'PASSWORD': os.getenv('DATABASE_PASSWORD', 'testingpw'),
|
||||||
'HOST': os.getenv('DATABASE_HOST', 'layersdb'),
|
'HOST': os.getenv('DATABASE_HOST', 'layersdb'),
|
||||||
'PORT': '',
|
'PORT': '',
|
||||||
|
|
|
@ -148,7 +148,7 @@ def yaml_comment(line):
|
||||||
|
|
||||||
|
|
||||||
# Add hostname, secret key, db info, and email host in docker-compose.yml
|
# Add hostname, secret key, db info, and email host in docker-compose.yml
|
||||||
def edit_dockercompose(hostname, dbpassword, secretkey, rmqpassword, portmapping, letsencrypt):
|
def edit_dockercompose(hostname, dbpassword, dbapassword, secretkey, rmqpassword, portmapping, letsencrypt):
|
||||||
filedata= readfile("docker-compose.yml")
|
filedata= readfile("docker-compose.yml")
|
||||||
in_layersweb = False
|
in_layersweb = False
|
||||||
in_layersweb_ports = False
|
in_layersweb_ports = False
|
||||||
|
@ -197,12 +197,15 @@ def edit_dockercompose(hostname, dbpassword, secretkey, rmqpassword, portmapping
|
||||||
elif '- "SECRET_KEY' in line:
|
elif '- "SECRET_KEY' in line:
|
||||||
format = line[0:line.find('- "SECRET_KEY')].replace("#", "")
|
format = line[0:line.find('- "SECRET_KEY')].replace("#", "")
|
||||||
newlines.append(format + '- "SECRET_KEY=' + secretkey + '"\n')
|
newlines.append(format + '- "SECRET_KEY=' + secretkey + '"\n')
|
||||||
|
elif '- "DATABASE_USER' in line:
|
||||||
|
format = line[0:line.find('- "DATABASE_USER')].replace("#", "")
|
||||||
|
newlines.append(format + '- "DATABASE_USER=layers"\n')
|
||||||
elif '- "DATABASE_PASSWORD' in line:
|
elif '- "DATABASE_PASSWORD' in line:
|
||||||
format = line[0:line.find('- "DATABASE_PASSWORD')].replace("#", "")
|
format = line[0:line.find('- "DATABASE_PASSWORD')].replace("#", "")
|
||||||
newlines.append(format + '- "DATABASE_PASSWORD=' + dbpassword + '"\n')
|
newlines.append(format + '- "DATABASE_PASSWORD=' + dbpassword + '"\n')
|
||||||
elif '- "MYSQL_ROOT_PASSWORD' in line:
|
elif '- "MYSQL_ROOT_PASSWORD' in line:
|
||||||
format = line[0:line.find('- "MYSQL_ROOT_PASSWORD')].replace("#", "")
|
format = line[0:line.find('- "MYSQL_ROOT_PASSWORD')].replace("#", "")
|
||||||
newlines.append(format + '- "MYSQL_ROOT_PASSWORD=' + dbpassword + '"\n')
|
newlines.append(format + '- "MYSQL_ROOT_PASSWORD=' + dbapassword + '"\n')
|
||||||
elif '- "RABBITMQ_DEFAULT_USER' in line:
|
elif '- "RABBITMQ_DEFAULT_USER' in line:
|
||||||
format = line[0:line.find('- "RABBITMQ_DEFAULT_USER')].replace("#", "")
|
format = line[0:line.find('- "RABBITMQ_DEFAULT_USER')].replace("#", "")
|
||||||
newlines.append(format + '- "RABBITMQ_DEFAULT_USER=layermq"\n')
|
newlines.append(format + '- "RABBITMQ_DEFAULT_USER=layermq"\n')
|
||||||
|
@ -380,14 +383,22 @@ def writefile(filename, data):
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
|
||||||
# Generate secret key and database password
|
|
||||||
secretkey = generatepasswords(50)
|
|
||||||
dbpassword = generatepasswords(10)
|
|
||||||
rmqpassword = generatepasswords(10)
|
|
||||||
|
|
||||||
## Get user arguments and modify config files
|
## Get user arguments and modify config files
|
||||||
updatemode, reinstmode, hostname, http_proxy, https_proxy, dbfile, port, proxymod, portmapping, no_https, cert, cert_key, letsencrypt = get_args()
|
updatemode, reinstmode, hostname, http_proxy, https_proxy, dbfile, port, proxymod, portmapping, no_https, cert, cert_key, letsencrypt = get_args()
|
||||||
|
|
||||||
|
if updatemode:
|
||||||
|
with open('docker-compose.yml', 'r') as f:
|
||||||
|
for line in f:
|
||||||
|
if 'MYSQL_ROOT_PASSWORD=' in line:
|
||||||
|
dbapassword = line.split('=')[1].rstrip().rstrip('"')
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# Generate secret key and database password
|
||||||
|
secretkey = generatepasswords(50)
|
||||||
|
dbapassword = generatepasswords(10)
|
||||||
|
dbpassword = generatepasswords(10)
|
||||||
|
rmqpassword = generatepasswords(10)
|
||||||
|
|
||||||
https_port = None
|
https_port = None
|
||||||
http_port = None
|
http_port = None
|
||||||
if not updatemode:
|
if not updatemode:
|
||||||
|
@ -414,14 +425,9 @@ if updatemode:
|
||||||
if not installed:
|
if not installed:
|
||||||
print("Application container not found - update mode can only be used on an existing installation")
|
print("Application container not found - update mode can only be used on an existing installation")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
with open('docker-compose.yml', 'r') as f:
|
if dbapassword == 'testingpw':
|
||||||
for line in f:
|
|
||||||
if 'DATABASE_PASSWORD=' in line:
|
|
||||||
pw = line.split('=')[1].rstrip().rstrip('"')
|
|
||||||
if pw == 'testingpw':
|
|
||||||
print("Update mode can only be used when previous configuration is still present in docker-compose.yml and other files")
|
print("Update mode can only be used when previous configuration is still present in docker-compose.yml and other files")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
break
|
|
||||||
elif installed and not reinstmode:
|
elif installed and not reinstmode:
|
||||||
print('Application already installed. Please use -u/--update to update or -r/--reinstall to reinstall')
|
print('Application already installed. Please use -u/--update to update or -r/--reinstall to reinstall')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
@ -466,7 +472,7 @@ if not updatemode:
|
||||||
if http_proxy or https_proxy:
|
if http_proxy or https_proxy:
|
||||||
edit_dockerfile(http_proxy, https_proxy)
|
edit_dockerfile(http_proxy, https_proxy)
|
||||||
|
|
||||||
edit_dockercompose(hostname, dbpassword, secretkey, rmqpassword, portmapping, letsencrypt)
|
edit_dockercompose(hostname, dbpassword, dbapassword, secretkey, rmqpassword, portmapping, letsencrypt)
|
||||||
|
|
||||||
edit_dockerfile_web(hostname, no_https)
|
edit_dockerfile_web(hostname, no_https)
|
||||||
|
|
||||||
|
@ -483,16 +489,42 @@ if return_code != 0:
|
||||||
time.sleep(8)
|
time.sleep(8)
|
||||||
while True:
|
while True:
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
return_code = subprocess.call("docker-compose run --rm layersapp /opt/migrate.sh", shell=True)
|
# Pass credentials through environment for slightly better security
|
||||||
|
# (avoids password being visible through ps or /proc/<pid>/cmdline)
|
||||||
|
env = os.environ.copy()
|
||||||
|
env['DATABASE_USER'] = 'root'
|
||||||
|
env['DATABASE_PASSWORD'] = dbapassword
|
||||||
|
return_code = subprocess.call("docker-compose run --rm -e DATABASE_USER -e DATABASE_PASSWORD layersapp /opt/migrate.sh", shell=True, env=env)
|
||||||
if return_code == 0:
|
if return_code == 0:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
print("Database server may not be ready; will try again.")
|
print("Database server may not be ready; will try again.")
|
||||||
|
|
||||||
if not updatemode:
|
if not updatemode:
|
||||||
|
# Create normal database user for app to use
|
||||||
|
with tempfile.NamedTemporaryFile('w', dir=os.getcwd(), delete=False) as tf:
|
||||||
|
sqlscriptfile = tf.name
|
||||||
|
tf.write("DROP USER IF EXISTS layers;")
|
||||||
|
tf.write("CREATE USER layers IDENTIFIED BY '%s';\n" % dbpassword)
|
||||||
|
tf.write("GRANT SELECT, UPDATE, INSERT, DELETE ON layersdb.* TO layers;\n")
|
||||||
|
tf.write("FLUSH PRIVILEGES;\n")
|
||||||
|
try:
|
||||||
|
# Pass credentials through environment for slightly better security
|
||||||
|
# (avoids password being visible through ps or /proc/<pid>/cmdline)
|
||||||
|
env = os.environ.copy()
|
||||||
|
env['MYSQL_PWD'] = dbapassword
|
||||||
|
return_code = subprocess.call("docker exec -i -e MYSQL_PWD layersdb mysql -uroot layersdb < " + sqlscriptfile, shell=True, env=env)
|
||||||
|
if return_code != 0:
|
||||||
|
print("Creating database user failed")
|
||||||
|
sys.exit(1)
|
||||||
|
finally:
|
||||||
|
os.remove(sqlscriptfile)
|
||||||
|
|
||||||
# Import the user's supplied data
|
# Import the user's supplied data
|
||||||
if dbfile:
|
if dbfile:
|
||||||
return_code = subprocess.call("docker exec -i layersdb mysql -uroot -p" + dbpassword + " layersdb " + " < " + dbfile, shell=True)
|
env = os.environ.copy()
|
||||||
|
env['MYSQL_PWD'] = dbapassword
|
||||||
|
return_code = subprocess.call("docker exec -i -e MYSQL_PWD layersdb mysql -uroot layersdb < " + dbfile, shell=True, env=env)
|
||||||
if return_code != 0:
|
if return_code != 0:
|
||||||
print("Database import failed")
|
print("Database import failed")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user