Revision dedfdca1
Added by Benoît PECCATTE about 7 years ago
rudder-server-relay/SOURCES/relay-api/relay_api/shared_files.py | ||
---|---|---|
# Extract a public key object from headers
|
||
def get_pubkey(header_info):
|
||
# validate header content first
|
||
if 'digest' not in header_info or 'pubkey' not in header_info:
|
||
if 'digest' not in header_info or 'short_pubkey' not in header_info:
|
||
raise ValueError("ERROR incomplete header, missing digest or public key")
|
||
pem = "-----BEGIN RSA PRIVATE KEY-----\n" + header_info['pubkey'] + "\n-----END RSA PRIVATE KEY-----\n"
|
||
pem = "-----BEGIN RSA PRIVATE KEY-----\n" + header_info['short_pubkey'] + "\n-----END RSA PRIVATE KEY-----\n"
|
||
return RSA.importKey(pem)
|
||
|
||
|
||
# Create expiry header line
|
||
def expiry_line(header_info):
|
||
if 'ttl' not in header_info:
|
||
raise ValueError("ERROR: No TTL provided")
|
||
else:
|
||
def expiry_line(header_info, ttl_value):
|
||
if ttl_value is None or ttl_value == '':
|
||
if 'ttl' not in header_info:
|
||
raise ValueError("ERROR: No TTL provided")
|
||
ttl = parse_ttl(header_info['ttl'])
|
||
expires = datetime.datetime.utcnow() + ttl # we take utcnow because we write a unix timestamp
|
||
timestamp = int((expires - datetime.datetime(1970, 1, 1)).total_seconds()) # convert to unix timestamp
|
||
return "expires=" + str(timestamp) + "\n"
|
||
else:
|
||
ttl = parse_ttl(ttl_value)
|
||
expires = datetime.datetime.utcnow() + ttl # we take utcnow because we write a unix timestamp
|
||
delta = expires - datetime.datetime(1970, 1, 1)
|
||
timestamp = delta.days*24*3600 + delta.seconds # convert to unix timestamp
|
||
return "expires=" + str(timestamp) + "\n"
|
||
|
||
|
||
# Hash a message with a given algorithm
|
||
... | ... | |
# - nodes the content of the nodes_list file
|
||
# - my_uuid uuid of the current relay (self)
|
||
# - shared_path the shared-files directory path
|
||
# - ttl duration to keep the file
|
||
# Returns the full path of the created file
|
||
def shared_files_put(target_uuid, source_uuid, file_id, data_stream, nodes, my_uuid, shared_path):
|
||
def shared_files_put(target_uuid, source_uuid, file_id, data_stream, nodes, my_uuid, shared_path, ttl):
|
||
header = get_header(data_stream)
|
||
info = parse_header(header)
|
||
|
||
... | ... | |
pubkey = get_pubkey(info)
|
||
if source_uuid not in nodes:
|
||
raise ValueError("ERROR unknown source node: " + str(source_uuid))
|
||
if "keyhash" not in nodes[source_uuid]:
|
||
if "key-hash" not in nodes[source_uuid]:
|
||
raise ValueError("ERROR invalid nodes file on the server for " + source_uuid)
|
||
keyhash = nodes[source_uuid]["keyhash"]
|
||
keyhash = nodes[source_uuid]["key-hash"]
|
||
|
||
# validate key
|
||
if not validate_key(pubkey, keyhash):
|
||
... | ... | |
raise ValueError("ERROR invalid signature")
|
||
|
||
# add headers
|
||
header += expiry_line(info)
|
||
header += expiry_line(info, ttl)
|
||
# replace hash by a guaranteed one
|
||
header = re.sub(r'hash_value=.*?\n', "hash_value=" + message_hash + "\n", header)
|
||
|
rudder-server-relay/SOURCES/relay-api/relay_api/views.py | ||
---|---|---|
def put_file(target_uuid, source_uuid, file_id):
|
||
try:
|
||
nodes = get_nodes_list(NODESLIST_FILE)
|
||
ttl = request.args.get('ttl', '')
|
||
my_uuid = get_file_content(UUID_FILE)
|
||
if target_uuid not in nodes:
|
||
# forward the file if the node is unknown
|
||
policy_server = get_file_content(POLICY_SERVER_FILE)
|
||
if policy_server == "root":
|
||
if my_uuid == "root":
|
||
return format_response("Unknown UUID: "+target_uuid, 404)
|
||
else:
|
||
url = "https://"+policy_server+"/rudder/relay-api/shared-files/" + target_uuid + "/" + source_uuid + "/" + file_id + "?hash=" + file_hash
|
||
policy_server = get_file_content(POLICY_SERVER_FILE)
|
||
url = "https://"+policy_server+"/rudder/relay-api/shared-files/" + target_uuid + "/" + source_uuid + "/" + file_id + "?ttl=" + ttl
|
||
res = shared_files_put_forward(request.stream, url)
|
||
else:
|
||
# process the file if it is known
|
||
my_uuid = get_file_content(UUID_FILE)
|
||
filename = shared_files_put(target_uuid, source_uuid, file_id, request.stream, nodes, my_uuid, SHARED_FILES_PATH)
|
||
filename = shared_files_put(target_uuid, source_uuid, file_id, request.stream, nodes, my_uuid, SHARED_FILES_PATH, ttl)
|
||
if API_DEBUGINFO:
|
||
res = "OK\nWritten to: " + filename + "\n"
|
||
else:
|
||
... | ... | |
try:
|
||
nodes = get_nodes_list(NODESLIST_FILE)
|
||
file_hash = request.args.get('hash', '')
|
||
my_uuid = get_file_content(UUID_FILE)
|
||
if target_uuid not in nodes:
|
||
# forward the request if the node is unknown
|
||
policy_server = get_file_content(POLICY_SERVER_FILE)
|
||
if policy_server == "root":
|
||
if my_uuid == "root":
|
||
return format_response("Unknown UUID: "+target_uuid, 404)
|
||
else:
|
||
policy_server = get_file_content(POLICY_SERVER_FILE)
|
||
url = "https://"+policy_server+"/rudder/relay-api/shared-files/" + target_uuid + "/" + source_uuid + "/" + file_id + "?hash=" + file_hash
|
||
res = shared_files_head_forward(url)
|
||
else:
|
||
# process the request if it is known
|
||
my_uuid = get_file_content(UUID_FILE)
|
||
res = shared_files_head(target_uuid, source_uuid, file_id, file_hash, nodes, my_uuid, SHARED_FILES_PATH)
|
||
if res:
|
||
return format_response("", 200)
|
rudder-webapp/SOURCES/rudder-apache-webapp-common.conf | ||
---|---|---|
# Prevent Chrome loop detection to block the page after too many
|
||
# page reloads.
|
||
<LocationMatch "/rudder">
|
||
<LocationMatch "/rudder(?!/relay-api|/api)">
|
||
Header add X-Chrome-Exponential-Throttling "disable"
|
||
</LocationMatch>
|
||
|
Also available in: Unified diff
Fixes #10138: pass ttl through url parameters in sharedfiles api