ot-gcc-get-token 0.1.0__tar.gz
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 ot-gcc-get-token might be problematic. Click here for more details.
- ot_gcc_get_token-0.1.0/PKG-INFO +36 -0
- ot_gcc_get_token-0.1.0/README.md +26 -0
- ot_gcc_get_token-0.1.0/pyproject.toml +21 -0
- ot_gcc_get_token-0.1.0/setup.cfg +4 -0
- ot_gcc_get_token-0.1.0/src/ot_gcc_get_token/__init__.py +1 -0
- ot_gcc_get_token-0.1.0/src/ot_gcc_get_token/__main__.py +3 -0
- ot_gcc_get_token-0.1.0/src/ot_gcc_get_token/cli.py +239 -0
- ot_gcc_get_token-0.1.0/src/ot_gcc_get_token.egg-info/PKG-INFO +36 -0
- ot_gcc_get_token-0.1.0/src/ot_gcc_get_token.egg-info/SOURCES.txt +12 -0
- ot_gcc_get_token-0.1.0/src/ot_gcc_get_token.egg-info/dependency_links.txt +1 -0
- ot_gcc_get_token-0.1.0/src/ot_gcc_get_token.egg-info/entry_points.txt +2 -0
- ot_gcc_get_token-0.1.0/src/ot_gcc_get_token.egg-info/requires.txt +1 -0
- ot_gcc_get_token-0.1.0/src/ot_gcc_get_token.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ot-gcc-get-token
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Launch Chrome/Edge, wait for OIDC login to the AWS Agentic Wizard, and print the access token to stdout.
|
|
5
|
+
Classifier: Programming Language :: Python :: 3
|
|
6
|
+
Classifier: Operating System :: OS Independent
|
|
7
|
+
Requires-Python: >=3.8
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: playwright>=1.40
|
|
10
|
+
|
|
11
|
+
# ot-gcc-get-token
|
|
12
|
+
|
|
13
|
+
Opens Chrome or Edge with a dedicated profile, waits for you to sign in to the
|
|
14
|
+
AWS Agentic Wizard (OIDC), then prints the access token to **stdout**. All
|
|
15
|
+
status messages go to stderr, so it is safe to use in scripts.
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
pip install ot-gcc-get-token
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
ot-gcc-get-token
|
|
27
|
+
ot-gcc-get-token --wizard-url https://your-wizard.example.net/
|
|
28
|
+
TOKEN=$(ot-gcc-get-token)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The wizard URL can also be set with the `WIZARD_URL` environment variable.
|
|
32
|
+
The browser profile is stored in `~/.aws-agentic-wizard`, so you stay signed
|
|
33
|
+
in between runs.
|
|
34
|
+
|
|
35
|
+
Playwright is only used to attach to the browser over CDP (port 9222); no
|
|
36
|
+
Playwright browser download is required.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# ot-gcc-get-token
|
|
2
|
+
|
|
3
|
+
Opens Chrome or Edge with a dedicated profile, waits for you to sign in to the
|
|
4
|
+
AWS Agentic Wizard (OIDC), then prints the access token to **stdout**. All
|
|
5
|
+
status messages go to stderr, so it is safe to use in scripts.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
pip install ot-gcc-get-token
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
ot-gcc-get-token
|
|
17
|
+
ot-gcc-get-token --wizard-url https://your-wizard.example.net/
|
|
18
|
+
TOKEN=$(ot-gcc-get-token)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The wizard URL can also be set with the `WIZARD_URL` environment variable.
|
|
22
|
+
The browser profile is stored in `~/.aws-agentic-wizard`, so you stay signed
|
|
23
|
+
in between runs.
|
|
24
|
+
|
|
25
|
+
Playwright is only used to attach to the browser over CDP (port 9222); no
|
|
26
|
+
Playwright browser download is required.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "ot-gcc-get-token"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Launch Chrome/Edge, wait for OIDC login to the AWS Agentic Wizard, and print the access token to stdout."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
dependencies = ["playwright>=1.40"]
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Programming Language :: Python :: 3",
|
|
14
|
+
"Operating System :: OS Independent",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[project.scripts]
|
|
18
|
+
ot-gcc-get-token = "ot_gcc_get_token.cli:main"
|
|
19
|
+
|
|
20
|
+
[tool.setuptools.packages.find]
|
|
21
|
+
where = ["src"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import base64
|
|
3
|
+
import json
|
|
4
|
+
import os
|
|
5
|
+
import pathlib
|
|
6
|
+
import shutil
|
|
7
|
+
import subprocess
|
|
8
|
+
import sys
|
|
9
|
+
import time
|
|
10
|
+
import urllib.request
|
|
11
|
+
|
|
12
|
+
from playwright.sync_api import sync_playwright
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
DEFAULT_URL = "https://aws-agentic-wizard-gcc-dev.otxlab.net/"
|
|
16
|
+
|
|
17
|
+
CDP_PORT = 9222
|
|
18
|
+
|
|
19
|
+
PROFILE = pathlib.Path.home() / ".aws-agentic-wizard"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def log(message):
|
|
23
|
+
print(message, file=sys.stderr)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def find_browser():
|
|
27
|
+
candidates = [
|
|
28
|
+
os.path.expandvars(r"%ProgramFiles%\Google\Chrome\Application\chrome.exe"),
|
|
29
|
+
os.path.expandvars(r"%ProgramFiles(x86)%\Google\Chrome\Application\chrome.exe"),
|
|
30
|
+
os.path.expandvars(r"%LocalAppData%\Google\Chrome\Application\chrome.exe"),
|
|
31
|
+
os.path.expandvars(r"%ProgramFiles(x86)%\Microsoft\Edge\Application\msedge.exe"),
|
|
32
|
+
os.path.expandvars(r"%ProgramFiles%\Microsoft\Edge\Application\msedge.exe"),
|
|
33
|
+
os.path.expandvars(r"%LocalAppData%\Microsoft\Edge\Application\msedge.exe"),
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
for path in candidates:
|
|
37
|
+
if os.path.isfile(path):
|
|
38
|
+
return path
|
|
39
|
+
|
|
40
|
+
for command in ("chrome", "msedge"):
|
|
41
|
+
path = shutil.which(command)
|
|
42
|
+
if path:
|
|
43
|
+
return path
|
|
44
|
+
|
|
45
|
+
return None
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def start_browser(url):
|
|
49
|
+
browser = find_browser()
|
|
50
|
+
|
|
51
|
+
if not browser:
|
|
52
|
+
raise RuntimeError("Chrome or Microsoft Edge was not found.")
|
|
53
|
+
|
|
54
|
+
PROFILE.mkdir(parents=True, exist_ok=True)
|
|
55
|
+
|
|
56
|
+
command = [
|
|
57
|
+
browser,
|
|
58
|
+
f"--remote-debugging-port={CDP_PORT}",
|
|
59
|
+
f"--user-data-dir={PROFILE}",
|
|
60
|
+
"--no-first-run",
|
|
61
|
+
"--no-default-browser-check",
|
|
62
|
+
url,
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
log("Starting browser...")
|
|
66
|
+
|
|
67
|
+
subprocess.Popen(
|
|
68
|
+
command,
|
|
69
|
+
stdout=subprocess.DEVNULL,
|
|
70
|
+
stderr=subprocess.DEVNULL,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def wait_for_cdp(timeout=30):
|
|
75
|
+
deadline = time.time() + timeout
|
|
76
|
+
|
|
77
|
+
while time.time() < deadline:
|
|
78
|
+
try:
|
|
79
|
+
with urllib.request.urlopen(
|
|
80
|
+
f"http://127.0.0.1:{CDP_PORT}/json/version",
|
|
81
|
+
timeout=1,
|
|
82
|
+
) as response:
|
|
83
|
+
return json.load(response)
|
|
84
|
+
except Exception:
|
|
85
|
+
time.sleep(0.5)
|
|
86
|
+
|
|
87
|
+
raise RuntimeError(
|
|
88
|
+
"Browser started but CDP endpoint did not become available."
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
GET_TOKEN_JS = """
|
|
93
|
+
() => {
|
|
94
|
+
const key = Object.keys(sessionStorage)
|
|
95
|
+
.find(k => k.startsWith("oidc.user"));
|
|
96
|
+
|
|
97
|
+
if (!key) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const raw = sessionStorage.getItem(key);
|
|
102
|
+
|
|
103
|
+
if (!raw) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
const data = JSON.parse(raw);
|
|
109
|
+
return data.access_token || null;
|
|
110
|
+
} catch (e) {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def find_wizard_page(browser, url):
|
|
118
|
+
base = url.rstrip("/")
|
|
119
|
+
|
|
120
|
+
for context in browser.contexts:
|
|
121
|
+
for page in context.pages:
|
|
122
|
+
try:
|
|
123
|
+
if page.url.startswith(base):
|
|
124
|
+
return page
|
|
125
|
+
except Exception:
|
|
126
|
+
pass
|
|
127
|
+
|
|
128
|
+
return None
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def decode_jwt(token):
|
|
132
|
+
parts = token.split(".")
|
|
133
|
+
|
|
134
|
+
if len(parts) != 3:
|
|
135
|
+
return None
|
|
136
|
+
|
|
137
|
+
payload = parts[1]
|
|
138
|
+
payload += "=" * (-len(payload) % 4)
|
|
139
|
+
|
|
140
|
+
try:
|
|
141
|
+
return json.loads(base64.urlsafe_b64decode(payload))
|
|
142
|
+
except Exception:
|
|
143
|
+
return None
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def run():
|
|
147
|
+
parser = argparse.ArgumentParser(
|
|
148
|
+
prog="ot-gcc-get-token",
|
|
149
|
+
description=(
|
|
150
|
+
"Open Chrome/Edge, wait for OIDC login to the AWS Agentic "
|
|
151
|
+
"Wizard, and print the access token to stdout."
|
|
152
|
+
),
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
parser.add_argument(
|
|
156
|
+
"--wizard-url",
|
|
157
|
+
default=os.environ.get("WIZARD_URL", DEFAULT_URL),
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
parser.add_argument(
|
|
161
|
+
"--refresh",
|
|
162
|
+
action="store_true",
|
|
163
|
+
help="Open/re-authenticate instead of relying on current session",
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
args = parser.parse_args()
|
|
167
|
+
|
|
168
|
+
url = args.wizard_url
|
|
169
|
+
|
|
170
|
+
with sync_playwright() as pw:
|
|
171
|
+
# Start our own browser.
|
|
172
|
+
start_browser(url)
|
|
173
|
+
|
|
174
|
+
# Wait until Chrome exposes CDP.
|
|
175
|
+
info = wait_for_cdp()
|
|
176
|
+
|
|
177
|
+
log(f"Connected to: {info.get('Browser', 'browser')}")
|
|
178
|
+
|
|
179
|
+
# Attach Playwright.
|
|
180
|
+
browser = pw.chromium.connect_over_cdp(f"http://127.0.0.1:{CDP_PORT}")
|
|
181
|
+
|
|
182
|
+
# Find existing wizard tab.
|
|
183
|
+
page = find_wizard_page(browser, url)
|
|
184
|
+
|
|
185
|
+
# If it isn't open, create a tab.
|
|
186
|
+
if page is None:
|
|
187
|
+
log("Opening wizard...")
|
|
188
|
+
context = browser.contexts[0]
|
|
189
|
+
page = context.new_page()
|
|
190
|
+
page.goto(url, wait_until="domcontentloaded")
|
|
191
|
+
|
|
192
|
+
page.bring_to_front()
|
|
193
|
+
|
|
194
|
+
log("Waiting for authentication...")
|
|
195
|
+
|
|
196
|
+
# Wait until OIDC session appears.
|
|
197
|
+
page.wait_for_function(
|
|
198
|
+
"""
|
|
199
|
+
() => Object.keys(sessionStorage)
|
|
200
|
+
.some(k => k.startsWith("oidc.user"))
|
|
201
|
+
""",
|
|
202
|
+
timeout=300000,
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
log("Authenticated session detected.")
|
|
206
|
+
|
|
207
|
+
token = page.evaluate(GET_TOKEN_JS)
|
|
208
|
+
|
|
209
|
+
if not token:
|
|
210
|
+
raise RuntimeError(
|
|
211
|
+
"OIDC session was found, but access_token was not found."
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
claims = decode_jwt(token)
|
|
215
|
+
|
|
216
|
+
if claims:
|
|
217
|
+
if "exp" in claims:
|
|
218
|
+
remaining = int(claims["exp"] - time.time())
|
|
219
|
+
log(f"Token expires in {remaining // 60} minutes.")
|
|
220
|
+
|
|
221
|
+
if "tenant_id" in claims:
|
|
222
|
+
log(f"tenant_id: {claims['tenant_id']}")
|
|
223
|
+
|
|
224
|
+
# ONLY token goes to stdout.
|
|
225
|
+
print(token)
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def main():
|
|
229
|
+
try:
|
|
230
|
+
run()
|
|
231
|
+
except KeyboardInterrupt:
|
|
232
|
+
sys.exit(130)
|
|
233
|
+
except Exception as exc:
|
|
234
|
+
print(f"ERROR: {exc}", file=sys.stderr)
|
|
235
|
+
sys.exit(1)
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
if __name__ == "__main__":
|
|
239
|
+
main()
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ot-gcc-get-token
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Launch Chrome/Edge, wait for OIDC login to the AWS Agentic Wizard, and print the access token to stdout.
|
|
5
|
+
Classifier: Programming Language :: Python :: 3
|
|
6
|
+
Classifier: Operating System :: OS Independent
|
|
7
|
+
Requires-Python: >=3.8
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: playwright>=1.40
|
|
10
|
+
|
|
11
|
+
# ot-gcc-get-token
|
|
12
|
+
|
|
13
|
+
Opens Chrome or Edge with a dedicated profile, waits for you to sign in to the
|
|
14
|
+
AWS Agentic Wizard (OIDC), then prints the access token to **stdout**. All
|
|
15
|
+
status messages go to stderr, so it is safe to use in scripts.
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
pip install ot-gcc-get-token
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
ot-gcc-get-token
|
|
27
|
+
ot-gcc-get-token --wizard-url https://your-wizard.example.net/
|
|
28
|
+
TOKEN=$(ot-gcc-get-token)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The wizard URL can also be set with the `WIZARD_URL` environment variable.
|
|
32
|
+
The browser profile is stored in `~/.aws-agentic-wizard`, so you stay signed
|
|
33
|
+
in between runs.
|
|
34
|
+
|
|
35
|
+
Playwright is only used to attach to the browser over CDP (port 9222); no
|
|
36
|
+
Playwright browser download is required.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
setup.cfg
|
|
4
|
+
src/ot_gcc_get_token/__init__.py
|
|
5
|
+
src/ot_gcc_get_token/__main__.py
|
|
6
|
+
src/ot_gcc_get_token/cli.py
|
|
7
|
+
src/ot_gcc_get_token.egg-info/PKG-INFO
|
|
8
|
+
src/ot_gcc_get_token.egg-info/SOURCES.txt
|
|
9
|
+
src/ot_gcc_get_token.egg-info/dependency_links.txt
|
|
10
|
+
src/ot_gcc_get_token.egg-info/entry_points.txt
|
|
11
|
+
src/ot_gcc_get_token.egg-info/requires.txt
|
|
12
|
+
src/ot_gcc_get_token.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
playwright>=1.40
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ot_gcc_get_token
|