gam7 7.3.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of gam7 might be problematic. Click here for more details.

Files changed (72) hide show
  1. gam/__init__.py +77555 -0
  2. gam/__main__.py +40 -0
  3. gam/atom/__init__.py +1460 -0
  4. gam/atom/auth.py +41 -0
  5. gam/atom/client.py +214 -0
  6. gam/atom/core.py +535 -0
  7. gam/atom/data.py +327 -0
  8. gam/atom/http.py +354 -0
  9. gam/atom/http_core.py +599 -0
  10. gam/atom/http_interface.py +144 -0
  11. gam/atom/mock_http.py +123 -0
  12. gam/atom/mock_http_core.py +313 -0
  13. gam/atom/mock_service.py +235 -0
  14. gam/atom/service.py +723 -0
  15. gam/atom/token_store.py +105 -0
  16. gam/atom/url.py +130 -0
  17. gam/cacerts.pem +1130 -0
  18. gam/cbcm-v1.1beta1.json +593 -0
  19. gam/contactdelegation-v1.json +249 -0
  20. gam/datastudio-v1.json +486 -0
  21. gam/gamlib/__init__.py +17 -0
  22. gam/gamlib/glaction.py +308 -0
  23. gam/gamlib/glapi.py +837 -0
  24. gam/gamlib/glcfg.py +616 -0
  25. gam/gamlib/glclargs.py +1184 -0
  26. gam/gamlib/glentity.py +831 -0
  27. gam/gamlib/glgapi.py +817 -0
  28. gam/gamlib/glgdata.py +98 -0
  29. gam/gamlib/glglobals.py +307 -0
  30. gam/gamlib/glindent.py +46 -0
  31. gam/gamlib/glmsgs.py +547 -0
  32. gam/gamlib/glskus.py +246 -0
  33. gam/gamlib/gluprop.py +279 -0
  34. gam/gamlib/glverlibs.py +33 -0
  35. gam/gamlib/yubikey.py +202 -0
  36. gam/gdata/__init__.py +825 -0
  37. gam/gdata/alt/__init__.py +20 -0
  38. gam/gdata/alt/app_engine.py +101 -0
  39. gam/gdata/alt/appengine.py +321 -0
  40. gam/gdata/apps/__init__.py +526 -0
  41. gam/gdata/apps/audit/__init__.py +1 -0
  42. gam/gdata/apps/audit/service.py +278 -0
  43. gam/gdata/apps/contacts/__init__.py +874 -0
  44. gam/gdata/apps/contacts/service.py +355 -0
  45. gam/gdata/apps/service.py +544 -0
  46. gam/gdata/apps/sites/__init__.py +283 -0
  47. gam/gdata/apps/sites/service.py +246 -0
  48. gam/gdata/service.py +1714 -0
  49. gam/gdata/urlfetch.py +247 -0
  50. gam/googleapiclient/__init__.py +27 -0
  51. gam/googleapiclient/_auth.py +167 -0
  52. gam/googleapiclient/_helpers.py +207 -0
  53. gam/googleapiclient/channel.py +315 -0
  54. gam/googleapiclient/discovery.py +1662 -0
  55. gam/googleapiclient/discovery_cache/__init__.py +78 -0
  56. gam/googleapiclient/discovery_cache/appengine_memcache.py +55 -0
  57. gam/googleapiclient/discovery_cache/base.py +46 -0
  58. gam/googleapiclient/discovery_cache/file_cache.py +145 -0
  59. gam/googleapiclient/errors.py +197 -0
  60. gam/googleapiclient/http.py +1962 -0
  61. gam/googleapiclient/mimeparse.py +183 -0
  62. gam/googleapiclient/model.py +429 -0
  63. gam/googleapiclient/schema.py +317 -0
  64. gam/googleapiclient/version.py +15 -0
  65. gam/iso8601/__init__.py +28 -0
  66. gam/iso8601/iso8601.py +160 -0
  67. gam/serviceaccountlookup-v1.json +141 -0
  68. gam/six.py +982 -0
  69. gam7-7.3.4.dist-info/METADATA +69 -0
  70. gam7-7.3.4.dist-info/RECORD +72 -0
  71. gam7-7.3.4.dist-info/WHEEL +4 -0
  72. gam7-7.3.4.dist-info/licenses/LICENSE +201 -0
gam/gamlib/yubikey.py ADDED
@@ -0,0 +1,202 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Copyright (C) 2023 Ross Scroggs All Rights Reserved.
4
+ #
5
+ # All Rights Reserved.
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may
8
+ # not use this file except in compliance with the License. You may obtain
9
+ # a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16
+ # License for the specific language governing permissions and limitations
17
+ # under the License.
18
+
19
+ """YubiKey"""
20
+
21
+ import base64
22
+ import datetime
23
+ from secrets import SystemRandom
24
+ import string
25
+ import sys
26
+
27
+ from cryptography.hazmat.primitives import hashes, serialization
28
+ from cryptography.hazmat.primitives.asymmetric import padding
29
+ from smartcard.Exceptions import CardConnectionException
30
+ from ykman.device import list_all_devices
31
+ from ykman.piv import generate_self_signed_certificate, generate_chuid
32
+ from yubikit.piv import DEFAULT_MANAGEMENT_KEY, \
33
+ InvalidPinError, \
34
+ KEY_TYPE, \
35
+ MANAGEMENT_KEY_TYPE, \
36
+ PIN_POLICY, \
37
+ PivSession, \
38
+ OBJECT_ID, \
39
+ SLOT, \
40
+ TOUCH_POLICY
41
+ from yubikit.core.smartcard import ApduError, SmartCardConnection
42
+
43
+ YUBIKEY_CONNECTION_ERROR_RC = 80
44
+ YUBIKEY_INVALID_KEY_TYPE_RC = 81
45
+ YUBIKEY_INVALID_SLOT_RC = 82
46
+ YUBIKEY_INVALID_PIN_RC = 83
47
+ YUBIKEY_APDU_ERROR_RC = 84
48
+ YUBIKEY_VALUE_ERROR_RC = 85
49
+ YUBIKEY_MULTIPLE_CONNECTED_RC = 86
50
+ YUBIKEY_NOT_FOUND_RC = 87
51
+
52
+ from gam import mplock
53
+
54
+ from gam import systemErrorExit
55
+ from gam import readStdin
56
+ from gam import writeStdout
57
+
58
+ from gam.gamlib import glmsgs as Msg
59
+
60
+ PIN_PUK_CHARS = string.ascii_letters+string.digits+string.punctuation
61
+
62
+ class YubiKey():
63
+
64
+ def __init__(self, service_account_info=None):
65
+ self.key_type = None
66
+ self.slot = None
67
+ self.serial_number = None
68
+ self.pin = None
69
+ self.key_id = None
70
+ if service_account_info:
71
+ key_type = service_account_info.get('yubikey_key_type', 'RSA2048')
72
+ try:
73
+ self.key_type = getattr(KEY_TYPE, key_type.upper())
74
+ except AttributeError:
75
+ systemErrorExit(YUBIKEY_INVALID_KEY_TYPE_RC, f'{key_type} is not a valid value for yubikey_key_type')
76
+ slot = service_account_info.get('yubikey_slot', 'AUTHENTICATION')
77
+ try:
78
+ self.slot = getattr(SLOT, slot.upper())
79
+ except AttributeError:
80
+ systemErrorExit(YUBIKEY_INVALID_SLOT_RC, f'{slot} is not a valid value for yubikey_slot')
81
+ self.serial_number = service_account_info.get('yubikey_serial_number')
82
+ self.pin = service_account_info.get('yubikey_pin')
83
+ self.key_id = service_account_info.get('private_key_id')
84
+
85
+ def _connect(self):
86
+ try:
87
+ devices = list_all_devices()
88
+ for (device, info) in devices:
89
+ if info.serial == self.serial_number:
90
+ return device.open_connection(SmartCardConnection)
91
+ except CardConnectionException as err:
92
+ systemErrorExit(YUBIKEY_CONNECTION_ERROR_RC, f'YubiKey - {err}')
93
+
94
+ def get_certificate(self):
95
+ try:
96
+ conn = self._connect()
97
+ with conn:
98
+ session = PivSession(conn)
99
+ if self.pin:
100
+ try:
101
+ session.verify_pin(self.pin)
102
+ except InvalidPinError as err:
103
+ systemErrorExit(YUBIKEY_INVALID_PIN_RC, f'YubiKey - {err}')
104
+ try:
105
+ cert = session.get_certificate(self.slot)
106
+ except ApduError as err:
107
+ systemErrorExit(YUBIKEY_APDU_ERROR_RC, f'YubiKey - {err}')
108
+ cert_pem = cert.public_bytes(serialization.Encoding.PEM).decode()
109
+ publicKeyData = base64.b64encode(cert_pem.encode())
110
+ if isinstance(publicKeyData, bytes):
111
+ publicKeyData = publicKeyData.decode()
112
+ return publicKeyData
113
+ except ValueError as err:
114
+ systemErrorExit(YUBIKEY_VALUE_ERROR_RC, f'YubiKey - {err}')
115
+ except TypeError as err:
116
+ systemErrorExit(YUBIKEY_NOT_FOUND_RC, f'YubiKey - {err} - {Msg.IS_YUBIKEY_INSERTED}')
117
+
118
+ def get_serial_number(self):
119
+ try:
120
+ devices = list_all_devices()
121
+ if not devices:
122
+ systemErrorExit(YUBIKEY_NOT_FOUND_RC, Msg.COULD_NOT_FIND_ANY_YUBIKEY)
123
+ if self.serial_number:
124
+ for (_, info) in devices:
125
+ if info.serial == self.serial_number:
126
+ return info.serial
127
+ systemErrorExit(YUBIKEY_NOT_FOUND_RC, Msg.COULD_NOT_FIND_YUBIKEY_WITH_SERIAL.format(self.serial_number))
128
+ if len(devices) > 1:
129
+ serials = ', '.join([str(info.serial) for (_, info) in devices])
130
+ systemErrorExit(YUBIKEY_MULTIPLE_CONNECTED_RC, Msg.MULTIPLE_YUBIKEYS_CONNECTED.format(serials))
131
+ return devices[0][1].serial
132
+ except ValueError as err:
133
+ systemErrorExit(YUBIKEY_VALUE_ERROR_RC, f'YubiKey - {err}')
134
+
135
+ def reset_piv(self):
136
+ '''Resets YubiKey PIV app and generates new key for GAM to use.'''
137
+ reply = str(readStdin(Msg.CONFIRM_WIPE_YUBIKEY_PIV).lower().strip())
138
+ if reply != 'y':
139
+ sys.exit(1)
140
+ try:
141
+ conn = self._connect()
142
+ with conn:
143
+ piv = PivSession(conn)
144
+ piv.reset()
145
+ rnd = SystemRandom()
146
+ new_puk = ''.join(rnd.choice(PIN_PUK_CHARS) for _ in range(8))
147
+ new_pin = ''.join(rnd.choice(PIN_PUK_CHARS) for _ in range(8))
148
+ piv.change_puk('12345678', new_puk)
149
+ piv.change_pin('123456', new_pin)
150
+ writeStdout(Msg.YUBIKEY_PIN_SET_TO.format(new_pin))
151
+ piv.authenticate(MANAGEMENT_KEY_TYPE.TDES, DEFAULT_MANAGEMENT_KEY)
152
+ piv.verify_pin(new_pin)
153
+ writeStdout(Msg.YUBIKEY_GENERATING_NONEXPORTABLE_PRIVATE_KEY)
154
+ pubkey = piv.generate_key(SLOT.AUTHENTICATION,
155
+ KEY_TYPE.RSA2048,
156
+ PIN_POLICY.ALWAYS,
157
+ TOUCH_POLICY.NEVER)
158
+ now = datetime.datetime.utcnow()
159
+ valid_to = now + datetime.timedelta(days=36500)
160
+ subject = 'CN=GAM Created Key'
161
+ piv.authenticate(MANAGEMENT_KEY_TYPE.TDES, DEFAULT_MANAGEMENT_KEY)
162
+ piv.verify_pin(new_pin)
163
+ cert = generate_self_signed_certificate(piv,
164
+ SLOT.AUTHENTICATION,
165
+ pubkey,
166
+ subject,
167
+ now,
168
+ valid_to)
169
+ piv.put_certificate(SLOT.AUTHENTICATION, cert)
170
+ piv.put_object(OBJECT_ID.CHUID, generate_chuid())
171
+ except ValueError as err:
172
+ systemErrorExit(YUBIKEY_VALUE_ERROR_RC, f'YubiKey - {err}')
173
+ except TypeError as err:
174
+ systemErrorExit(YUBIKEY_NOT_FOUND_RC, f'YubiKey - {err} - {Msg.IS_YUBIKEY_INSERTED}')
175
+
176
+ def sign(self, message):
177
+ if mplock is not None:
178
+ mplock.acquire()
179
+ try:
180
+ conn = self._connect()
181
+ with conn:
182
+ session = PivSession(conn)
183
+ if self.pin:
184
+ try:
185
+ session.verify_pin(self.pin)
186
+ except InvalidPinError as err:
187
+ systemErrorExit(YUBIKEY_INVALID_PIN_RC, f'YubiKey - {err}')
188
+ try:
189
+ signed = session.sign(slot=self.slot,
190
+ key_type=self.key_type,
191
+ message=message,
192
+ hash_algorithm=hashes.SHA256(),
193
+ padding=padding.PKCS1v15())
194
+ except ApduError as err:
195
+ systemErrorExit(YUBIKEY_APDU_ERROR_RC, f'YubiKey - {err}')
196
+ except ValueError as err:
197
+ systemErrorExit(YUBIKEY_VALUE_ERROR_RC, f'YubiKey - {err}')
198
+ except TypeError as err:
199
+ systemErrorExit(YUBIKEY_NOT_FOUND_RC, f'YubiKey - {err} - {Msg.IS_YUBIKEY_INSERTED}')
200
+ if mplock is not None:
201
+ mplock.release()
202
+ return signed