| #!/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:]) |