diff options
Diffstat (limited to 'azurelinuxagent/utils')
| -rw-r--r-- | azurelinuxagent/utils/cryptutil.py | 121 | ||||
| -rw-r--r-- | azurelinuxagent/utils/fileutil.py | 7 | ||||
| -rw-r--r-- | azurelinuxagent/utils/osutil.py | 27 | ||||
| -rw-r--r-- | azurelinuxagent/utils/restutil.py | 22 | ||||
| -rw-r--r-- | azurelinuxagent/utils/shellutil.py | 6 | ||||
| -rw-r--r-- | azurelinuxagent/utils/textutil.py | 8 |
6 files changed, 148 insertions, 43 deletions
diff --git a/azurelinuxagent/utils/cryptutil.py b/azurelinuxagent/utils/cryptutil.py new file mode 100644 index 0000000..5ee5637 --- /dev/null +++ b/azurelinuxagent/utils/cryptutil.py @@ -0,0 +1,121 @@ +# Microsoft Azure Linux Agent +# +# Copyright 2014 Microsoft Corporation +# +# 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. +# +# Requires Python 2.4+ and Openssl 1.0+ +# + +import base64 +import struct +from azurelinuxagent.future import ustr, bytebuffer +from azurelinuxagent.exception import CryptError +import azurelinuxagent.utils.shellutil as shellutil + +class CryptUtil(object): + def __init__(self, openssl_cmd): + self.openssl_cmd = openssl_cmd + + def gen_transport_cert(self, prv_file, crt_file): + """ + Create ssl certificate for https communication with endpoint server. + """ + cmd = ("{0} req -x509 -nodes -subj /CN=LinuxTransport -days 32768 " + "-newkey rsa:2048 -keyout {1} " + "-out {2}").format(self.openssl_cmd, prv_file, crt_file) + shellutil.run(cmd) + + def get_pubkey_from_prv(self, file_name): + cmd = "{0} rsa -in {1} -pubout 2>/dev/null".format(self.openssl_cmd, + file_name) + pub = shellutil.run_get_output(cmd)[1] + return pub + + def get_pubkey_from_crt(self, file_name): + cmd = "{0} x509 -in {1} -pubkey -noout".format(self.openssl_cmd, + file_name) + pub = shellutil.run_get_output(cmd)[1] + return pub + + def get_thumbprint_from_crt(self, file_name): + cmd="{0} x509 -in {1} -fingerprint -noout".format(self.openssl_cmd, + file_name) + thumbprint = shellutil.run_get_output(cmd)[1] + thumbprint = thumbprint.rstrip().split('=')[1].replace(':', '').upper() + return thumbprint + + def decrypt_p7m(self, p7m_file, trans_prv_file, trans_cert_file, pem_file): + cmd = ("{0} cms -decrypt -in {1} -inkey {2} -recip {3} " + "| {4} pkcs12 -nodes -password pass: -out {5}" + "").format(self.openssl_cmd, p7m_file, trans_prv_file, + trans_cert_file, self.openssl_cmd, pem_file) + shellutil.run(cmd) + + def crt_to_ssh(self, input_file, output_file): + shellutil.run("ssh-keygen -i -m PKCS8 -f {0} >> {1}".format(input_file, + output_file)) + + def asn1_to_ssh(self, pubkey): + lines = pubkey.split("\n") + lines = [x for x in lines if not x.startswith("----")] + base64_encoded = "".join(lines) + try: + #TODO remove pyasn1 dependency + from pyasn1.codec.der import decoder as der_decoder + der_encoded = base64.b64decode(base64_encoded) + der_encoded = der_decoder.decode(der_encoded)[0][1] + key = der_decoder.decode(self.bits_to_bytes(der_encoded))[0] + n=key[0] + e=key[1] + keydata = bytearray() + keydata.extend(struct.pack('>I', len("ssh-rsa"))) + keydata.extend(b"ssh-rsa") + keydata.extend(struct.pack('>I', len(self.num_to_bytes(e)))) + keydata.extend(self.num_to_bytes(e)) + keydata.extend(struct.pack('>I', len(self.num_to_bytes(n)) + 1)) + keydata.extend(b"\0") + keydata.extend(self.num_to_bytes(n)) + keydata_base64 = base64.b64encode(bytebuffer(keydata)) + return ustr(b"ssh-rsa " + keydata_base64 + b"\n", + encoding='utf-8') + except ImportError as e: + raise CryptError("Failed to load pyasn1.codec.der") + + def num_to_bytes(self, num): + """ + Pack number into bytes. Retun as string. + """ + result = bytearray() + while num: + result.append(num & 0xFF) + num >>= 8 + result.reverse() + return result + + def bits_to_bytes(self, bits): + """ + Convert an array contains bits, [0,1] to a byte array + """ + index = 7 + byte_array = bytearray() + curr = 0 + for bit in bits: + curr = curr | (bit << index) + index = index - 1 + if index == -1: + byte_array.append(curr) + curr = 0 + index = 7 + return bytes(byte_array) + diff --git a/azurelinuxagent/utils/fileutil.py b/azurelinuxagent/utils/fileutil.py index 08592bc..5369a7c 100644 --- a/azurelinuxagent/utils/fileutil.py +++ b/azurelinuxagent/utils/fileutil.py @@ -27,7 +27,7 @@ import shutil import pwd import tempfile import azurelinuxagent.logger as logger -from azurelinuxagent.future import text +from azurelinuxagent.future import ustr import azurelinuxagent.utils.textutil as textutil def read_file(filepath, asbin=False, remove_bom=False, encoding='utf-8'): @@ -46,7 +46,7 @@ def read_file(filepath, asbin=False, remove_bom=False, encoding='utf-8'): if remove_bom: #Remove bom on bytes data before it is converted into string. data = textutil.remove_bom(data) - data = text(data, encoding=encoding) + data = ustr(data, encoding=encoding) return data def write_file(filepath, contents, asbin=False, encoding='utf-8', append=False): @@ -100,6 +100,7 @@ def replace_file(filepath, contents): return 1 return 0 + def base_name(path): head, tail = os.path.split(path) return tail @@ -151,7 +152,7 @@ def rm_dirs(*args): def update_conf_file(path, line_start, val, chk_err=False): conf = [] if not os.path.isfile(path) and chk_err: - raise Exception("Can't find config file:{0}".format(path)) + raise IOError("Can't find config file:{0}".format(path)) conf = read_file(path).split('\n') conf = [x for x in conf if not x.startswith(line_start)] conf.append(val) diff --git a/azurelinuxagent/utils/osutil.py b/azurelinuxagent/utils/osutil.py deleted file mode 100644 index 9de47e7..0000000 --- a/azurelinuxagent/utils/osutil.py +++ /dev/null @@ -1,27 +0,0 @@ -# Microsoft Azure Linux Agent -# -# Copyright 2014 Microsoft Corporation -# -# 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. -# -# Requires Python 2.4+ and Openssl 1.0+ -# - -""" -Load OSUtil implementation from azurelinuxagent.distro -""" -from azurelinuxagent.distro.default.osutil import OSUtilError -import azurelinuxagent.distro.loader as loader - -OSUTIL = loader.get_osutil() - diff --git a/azurelinuxagent/utils/restutil.py b/azurelinuxagent/utils/restutil.py index 2acfa57..2e8b0be 100644 --- a/azurelinuxagent/utils/restutil.py +++ b/azurelinuxagent/utils/restutil.py @@ -21,8 +21,9 @@ import time import platform import os import subprocess -import azurelinuxagent.logger as logger import azurelinuxagent.conf as conf +import azurelinuxagent.logger as logger +from azurelinuxagent.exception import HttpError from azurelinuxagent.future import httpclient, urlparse """ @@ -31,9 +32,6 @@ REST api util functions RETRY_WAITING_INTERVAL = 10 -class HttpError(Exception): - pass - def _parse_url(url): o = urlparse(url) rel_uri = o.path @@ -51,8 +49,8 @@ def get_http_proxy(): Get http_proxy and https_proxy from environment variables. Username and password is not supported now. """ - host = conf.get("HttpProxy.Host", None) - port = conf.get("HttpProxy.Port", None) + host = conf.get_httpproxy_host() + port = conf.get_httpproxy_port() return (host, port) def _http_request(method, host, rel_uri, port=None, data=None, secure=False, @@ -61,7 +59,7 @@ def _http_request(method, host, rel_uri, port=None, data=None, secure=False, if secure: port = 443 if port is None else port if proxy_host is not None and proxy_port is not None: - conn = httpclient.HTTPSConnection(proxy_host, proxy_port) + conn = httpclient.HTTPSConnection(proxy_host, proxy_port, timeout=10) conn.set_tunnel(host, port) #If proxy is used, full url is needed. url = "https://{0}:{1}{2}".format(host, port, rel_uri) @@ -71,7 +69,7 @@ def _http_request(method, host, rel_uri, port=None, data=None, secure=False, else: port = 80 if port is None else port if proxy_host is not None and proxy_port is not None: - conn = httpclient.HTTPConnection(proxy_host, proxy_port) + conn = httpclient.HTTPConnection(proxy_host, proxy_port, timeout=10) #If proxy is used, full url is needed. url = "http://{0}:{1}{2}".format(host, port, rel_uri) else: @@ -128,8 +126,12 @@ def http_request(method, url, data, headers=None, max_retry=3, chk_proxy=False): if retry < max_retry - 1: logger.info("Retry={0}, {1} {2}", retry, method, url) time.sleep(RETRY_WAITING_INTERVAL) - - raise HttpError("HTTP Err: {0} {1}".format(method, url)) + + if url is not None and len(url) > 100: + url_log = url[0: 100] #In case the url is too long + else: + url_log = url + raise HttpError("HTTP Err: {0} {1}".format(method, url_log)) def http_get(url, headers=None, max_retry=3, chk_proxy=False): return http_request("GET", url, data=None, headers=headers, diff --git a/azurelinuxagent/utils/shellutil.py b/azurelinuxagent/utils/shellutil.py index 372c78a..98871a1 100644 --- a/azurelinuxagent/utils/shellutil.py +++ b/azurelinuxagent/utils/shellutil.py @@ -20,7 +20,7 @@ import platform import os import subprocess -from azurelinuxagent.future import text +from azurelinuxagent.future import ustr import azurelinuxagent.logger as logger if not hasattr(subprocess,'check_output'): @@ -75,9 +75,9 @@ def run_get_output(cmd, chk_err=True, log_cmd=True): logger.verb(u"run cmd '{0}'", cmd) try: output=subprocess.check_output(cmd,stderr=subprocess.STDOUT,shell=True) - output = text(output, encoding='utf-8', errors="backslashreplace") + output = ustr(output, encoding='utf-8', errors="backslashreplace") except subprocess.CalledProcessError as e : - output = text(e.output, encoding='utf-8', errors="backslashreplace") + output = ustr(e.output, encoding='utf-8', errors="backslashreplace") if chk_err: if log_cmd: logger.error(u"run cmd '{0}' failed", e.cmd) diff --git a/azurelinuxagent/utils/textutil.py b/azurelinuxagent/utils/textutil.py index e0f1395..851f98a 100644 --- a/azurelinuxagent/utils/textutil.py +++ b/azurelinuxagent/utils/textutil.py @@ -224,5 +224,13 @@ def gen_password_hash(password, crypt_id, salt_len): salt = "${0}${1}".format(crypt_id, salt) return crypt.crypt(password, salt) +def get_bytes_from_pem(pem_str): + base64_bytes = "" + for line in pem_str.split('\n'): + if "----" not in line: + base64_bytes += line + return base64_bytes + + Version = LooseVersion |
