5
5
import pkg_resources
6
6
import platform
7
7
import socket
8
+ from socket import socket , AF_INET , SOCK_DGRAM
9
+ import re
10
+ import struct
11
+ import time
8
12
13
+ from contextlib import closing
9
14
from collections import OrderedDict
10
15
from datetime import datetime , timedelta
11
16
from profilers import is_warm
@@ -18,6 +23,113 @@ class PosixCoreProfiler(Profiler):
18
23
19
24
"""Functions for specific data retreival."""
20
25
26
+ def check_time_drift ():
27
+ ## Ignores network latency to the NTP server.
28
+
29
+ NTP_PACKET_FORMAT = "!12I"
30
+ NTP_DELTA = 2208988800L # 1970-01-01 00:00:00
31
+ NTP_QUERY = '\x1b ' + 47 * '\0 '
32
+ host = "pool.ntp.org"
33
+ port = 123
34
+
35
+ with closing (socket (AF_INET , SOCK_DGRAM )) as s :
36
+ s .sendto (NTP_QUERY , ("pool.ntp.org" , 123 ))
37
+ msg , address = s .recvfrom (1024 )
38
+ local_time = time .time ()
39
+ unpacked = struct .unpack (NTP_PACKET_FORMAT ,
40
+ msg [0 :struct .calcsize (NTP_PACKET_FORMAT )])
41
+ ntp_time = unpacked [10 ] + float (unpacked [11 ]) / 2 ** 32 - NTP_DELTA
42
+
43
+ return abs (ntp_time - local_time )
44
+
45
+ def check_interesting_env_vars ():
46
+ ## Returns a subset of environment variables that are interesting:
47
+ ## secrets, etc.
48
+
49
+ interesting_vars = [
50
+ 'AWS_SESSION_TOKEN' ,
51
+ 'AWS_SECURITY_TOKEN' ,
52
+ "AWS_ACCESS_KEY_ID" ,
53
+ "AWS_SECRET_ACCESS_KEY" ,
54
+ ]
55
+
56
+ env_vars = os .environ .__dict__
57
+ interesting_subset = dict ((k , env_vars [k ]) for k in interesting_subset if k in env_vars )
58
+
59
+ return interesting_subset
60
+
61
+ def check_env_editable ():
62
+ os .environ ['profiler_test' ] = 'flag'
63
+
64
+ ## we check with a different method to demonstrate that it's not
65
+ ## just edited within 'environ'
66
+ res = call_shell_wrapper (['env | grep \' profiler_test\' ' ])
67
+
68
+ if res == 'profiler_test=flag\n ' :
69
+ return True
70
+ else :
71
+ return False
72
+
73
+ def check_source_editable ():
74
+ ## check if we can edit the file on disk
75
+ flag_string = 'profiler_test'
76
+
77
+ call_shell_wrapper (['echo "{}" >> {}' .format (flag_string , __file__ )])
78
+ res = call_shell_wrapper (['tail -n 1 {}' .format (__file__ )])
79
+
80
+ if res == '{}\n ' .format (flag_string ):
81
+ return True
82
+ else :
83
+ return False
84
+
85
+ def check_arbitrary_binary ():
86
+ ## Re: Lambda
87
+ ## I wasn't able to get executable permissions on the binary in the code dir
88
+ ## and didn't have permissions to edit with chmod.
89
+ ## We just attach a precompiled binary, move it to /tmp, and execute.
90
+
91
+ call_shell_wrapper (['mv profiler_bin /tmp' ])
92
+ call_shell_wrapper (['chmod +x /tmp/profiler_bin' ])
93
+ res = call_shell_wrapper (['/tmp/profiler_bin' ])
94
+
95
+ if res == 'custom profiler binary' :
96
+ return True
97
+ else :
98
+ return False
99
+
100
+ def check_other_runtimes ():
101
+ ## for now, just node. Can expand as wanted, thus we return a dict.
102
+
103
+ node_test = call_shell_wrapper (['node -e \' console.log("foo");\' ' ])
104
+
105
+ if node_test == 'foo\n ' :
106
+ return {'node' : True }
107
+ else :
108
+ return {'node' : False }
109
+
110
+
111
+ def check_docker_containers ():
112
+ docker_socket_locations = ["/var/run/docker.sock" ]
113
+
114
+ results = [os .path .ispath (f ) for f in docker_socket_locations ]
115
+
116
+ return any (results )
117
+
118
+ def check_capabilities ():
119
+ ## we assume (checked on lambda) that we are PID 1
120
+ ## see http://man7.org/linux/man-pages/man5/proc.5.html
121
+ ## If we can't check permissions, we assume none.
122
+
123
+ statline = call_shell_wrapper (["grep 'CapEff' /proc/1/status" ])
124
+
125
+ bitmask = re .match (r'CapEff:\t(\d+)\n' , res ).groups ()
126
+ flags = 0
127
+
128
+ if len (bitmask ) == 1 :
129
+ flags = int (bitmask [0 ])
130
+
131
+ return flags
132
+
21
133
def get_pwd ():
22
134
return call_shell_wrapper (["pwd" ])
23
135
@@ -177,7 +289,13 @@ def get_ipaddress():
177
289
"ps" : get_processes ,
178
290
"timestamp" : get_timestamp ,
179
291
"ipaddress" : get_ipaddress ,
180
- "uptime" : get_uptime
292
+ "uptime" : get_uptime ,
293
+ "time_drift" : check_time_drift ,
294
+ "env_subset" : check_interesting_env_vars ,
295
+ "source_editable" : check_source_editable ,
296
+ "other_runtimes" : check_other_runtimes ,
297
+ "docker_sockets" : check_docker_containers ,
298
+ "proc_capabilities" : check_capabilities
181
299
}
182
300
183
301
@staticmethod
0 commit comments