178 lines
4.9 KiB
Python
Executable File

#!/usr/bin/python
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
import sys
import getopt
import json
import os
import base64
from fcntl import flock, LOCK_EX, LOCK_UN
def main(argv):
fpath = ''
b64data = ''
try:
opts, args = getopt.getopt(argv, "f:d:")
except getopt.GetoptError:
print('params: -f <filename> -d <b64jsondata>')
sys.exit(2)
for opt, arg in opts:
if opt == '-f':
fpath = arg
elif opt == '-d':
b64data = arg
json_data = ''
if fpath != '':
fh = open(fpath, 'r')
json_data = json.loads(fh.read())
elif b64data != '':
json_data = json.loads(base64.b64decode(b64data))
else:
print('-f <filename> or -d <b64jsondata> required')
sys.exit(2)
for ip in json_data:
for item in json_data[ip]:
folder = item[0]
file = item[1]
data = item[2]
# process only valid data
if folder != "userdata" and folder != "metadata":
continue
if file == "":
continue
htaccess(ip, folder, file)
if data == "":
deletefile(ip, folder, file)
else:
createfile(ip, folder, file, data)
if fpath != '':
fh.close()
os.remove(fpath)
def deletefile(ip, folder, file):
datafile = "/var/www/html/" + folder + "/" + ip + "/" + file
if os.path.exists(datafile):
os.remove(datafile)
def writefile(dest, data, mode):
fh = open(dest, mode)
exflock(fh)
fh.write(data)
unflock(fh)
fh.close()
os.chmod(dest, 0o644)
def createfile(ip, folder, file, data):
dest = "/var/www/html/" + folder + "/" + ip + "/" + file
metamanifestdir = "/var/www/html/" + folder + "/" + ip
metamanifest = metamanifestdir + "/meta-data"
if data is not None:
# base64 decode userdata
if folder == "userdata" or folder == "user-data":
# need to pad data if it is not valid base 64
if len(data) % 4 != 0:
data += (4 - (len(data) % 4)) * "="
data = base64.b64decode(data)
if isinstance(data, str):
writefile(dest, data, "w")
elif isinstance(data, bytes):
writefile(dest, data, "wb")
else:
writefile(dest, "", "w")
if folder == "metadata" or folder == "meta-data":
try:
os.makedirs(metamanifestdir, 0o755)
except OSError as e:
# error 17 is already exists, we do it this way for concurrency
if e.errno != 17:
print("failed to make directories " + metamanifestdir + " due to :" + e.strerror)
sys.exit(1)
if os.path.exists(metamanifest):
fh = open(metamanifest, "r+a")
exflock(fh)
if file not in fh.read():
fh.write(file + '\n')
unflock(fh)
fh.close()
else:
fh = open(metamanifest, "w")
exflock(fh)
fh.write(file + '\n')
unflock(fh)
fh.close()
if os.path.exists(metamanifest):
os.chmod(metamanifest, 0o644)
def htaccess(ip, folder, file):
entry = "Options -Indexes\nOrder Deny,Allow\nDeny from all\nAllow from " + ip
htaccessFolder = "/var/www/html/" + folder + "/" + ip
htaccessFile = htaccessFolder+"/.htaccess"
try:
os.makedirs(htaccessFolder, 0o755)
except OSError as e:
# error 17 is already exists, we do it this way for sake of concurrency
if e.errno != 17:
print("failed to make directories " + htaccessFolder + " due to :" + e.strerror)
sys.exit(1)
fh = open(htaccessFile, "w")
exflock(fh)
fh.write(entry + '\n')
unflock(fh)
fh.close()
def exflock(file):
try:
flock(file, LOCK_EX)
except IOError as e:
print("failed to lock file" + file.name + " due to : " + e.strerror)
sys.exit(1)
return True
def unflock(file):
try:
flock(file, LOCK_UN)
except IOError as e:
print("failed to unlock file" + file.name + " due to : " + e.strerror)
sys.exit(1)
return True
if __name__ == "__main__":
main(sys.argv[1:])