如何通过 Selenium 抓取 AWS SSO 凭证 Python

How to Scrape the AWS SSO Credentials via Selenium Python

所以我工作的组织使用了一个流程,我们必须从 AWS SSO 控制台中抓取以下内容:

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_SESSION_TOKEN=

我的第一个想法是尝试使用 Curl,但是有一个重定向,因为它通过 SAML 集成到我们的 G-Suite 组织中,创建 LDAP 连接。因此,我唯一的想法是使用 selenium 登录、获取输出并登录。不幸的是,由于 OAuth 工作流的发生方式,我在通过有效负载选项时遇到了问题。

我的总体目标是使

的过程自动化
  1. 正在登录
  2. 单击特定操作
  3. 单击 SSO 控制台应用程序
  4. 正在复制 Access_Key、Secret_Access_Key 和 Session_Token,然后将其写入文件。

我可以毫无问题地注入用户名,但我无法使用 ID、名称和 XPATH 元素注入密码。这是 python 回溯:

 rbarrett@MacBook-Pro  ~/Projects/Mirantis/Train  python scrape_creds.py                       1 ↵  3201  13:06:17
The file does not exist
[<Response [301]>, <Response [302]>]
https://mirantis.awsapps.com/start/#/
Traceback (most recent call last):
  File "scrape_creds.py", line 99, in <module>
    password = browser.find_element_by_xpath("//*[@id='password']")
  File "/usr/local/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py", line 394, in find_element_by_xpath
    return self.find_element(by=By.XPATH, value=xpath)
  File "/usr/local/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py", line 976, in find_element
    return self.execute(Command.FIND_ELEMENT, {
  File "/usr/local/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
    self.error_handler.check_response(response)
  File "/usr/local/lib/python3.8/site-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//*[@id='password']"}
  (Session info: chrome=86.0.4240.75)

代码如下:

 rbarrett@MacBook-Pro  ~/Projects/Mirantis/Train  cat scrape_creds.py                            ✔  3206  13:25:30
#!/bin/python
# ===========================================================
# Created By: Richard Barrett
# Organization: Mirantis
# Department: Customer Success
# Purpose: AWS SSO Credential Scrape
# Date: 10/01/2020
# ===========================================================

import selenium
import shutil
import xlsxwriter
import os
import unittest
import requests
import subprocess
import getpass
import platform
import logging
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from datetime import date

decrypt = "gpg --output secrets_test.json --decrypt secrets.gpg"

if os.path.exists("secrets.gpg"):
      returned_value = subprocess.call(decrypt, shell=True)
else:
        print("The file does not exist")

import json
with open('secrets.json','r') as f:
      config = json.load(f)

r = requests.get('http://' + 'mirantis.awsapps.com/start#/')

print(r.history)
print(r.url)

# Definitions
# find_elements_by_name
# find_elements_by_xpath
# find_elements_by_link_text
# find_elements_by_partial_link_text
# find_elements_by_tag_name
# find_elements_by_class_name
# find_elements_by_css_selector

# System Variables
today = date.today()
date = today.strftime("%m/%d/%Y")
node = platform.node()
system = platform.system()
username = getpass.getuser()
version = platform.version()
current_directory = os.getcwd()

# URL Variables
login_url = 'https://mirantis.awsapps.com/start#/'

# Check for Version of Chrome

# Options
#options = webdriver.ChromeOptions()
#options.add_argument("download.default_directory=current_directory", "--headless")

# WebDriver Path for System
if platform.system() == ('Windows'):
    browser = webdriver.Chrome("C:\Program Files (x86)\Google\Chrome\chromedriver.exe")
elif platform.system() == ('Linux'):
    browser = webdriver.Chrome(executable_path='/home/rbarrett/Drivers/Google/Chrome/chromedriver')
elif platform.system() == ('Darwin'):
    browser = webdriver.Chrome(executable_path='/Users/rbarrett/Drivers/Google/Chrome/chromedriver')
else:
    print("Are you sure you have the Selenium Webdriver installed in the correct path?")

# Parent URL
browser.get("https://mirantis.awsapps.com/start#/")

time.sleep(10)

# Credentials NEEDS UNIT TEST
# EMAIL XPATH /html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[1]/div/form/span/section/div/div/div[1]/div/div[1]/div/div[1]/input
# EMAIL ID identifierId
username = browser.find_element_by_id("identifierId")
username.send_keys(config['user']['name'])
# Click Next
# Next Button ID XPATH //*[@id='identifierNext']/div/button/span
element = WebDriverWait(browser, 20).until(
        EC.element_to_be_clickable((By.ID, "identifierNext")))
element.click();

# Password Payload
# Password XPTAH //*[@id='password']
password = browser.find_element_by_xpath("//*[@id='password']")
password.send_keys(config['user']['password'])
# Click Next
# Next Button XPATH //*[@id="passwordNext"]/div/button/div[2]
#element = WebDriverWait(browser, 20).until(
#        EC.element_to_be_clickable((By.ID, "passwordNext")))
#element.click();
#time.sleep(15)

# Authentication submit.click()
# For XPATH = //portal-application
#element = WebDriverWait(browser, 20).until(
#        EC.element_to_be_clickable((By.XPATH, "//portal-application")))
#element.click();
#print("Opening AWS SSO for Train!")

问题是密码没有像它应该的那样被注入。 这是因为 Windows 开关吗?也许有更好的方法来抓取这些凭据,因为这些凭据每 12 小时过期一次。

所以我确实找到了处理这个问题的方法。 我无法通过它的原因是我需要等待特定元素可用。您可以通过使用等待或等待元素可点击来完成此操作。

# Credentials NEEDS UNIT TEST
# EMAIL XPATH /html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[1]/div/form/span/section/div/div/div[1]/div/div[1]/div/div[1]/input
# EMAIL ID identifierId
# XPATH //*[@id='identifierId']
#username = browser.find_element_by_xpath("//*[@id='identifierId']")
#username = browser.find_element_by_id("identifierId")
#username.send_keys(config['user']['name'])
element = WebDriverWait(browser, 20).until(
        EC.element_to_be_clickable((By.XPATH, "//*[@id='identifierId']")))
element.send_keys(config['user']['name'])
print("Sending Username...")


# Click Next
# Next Button ID XPATH //*[@id='identifierNext']/div/button/span
element = WebDriverWait(browser, 20).until(
        EC.element_to_be_clickable((By.ID, "identifierNext")))
element.click();
print("Clicking Next Button...")
time.sleep(2)

# Password Payload
# Password XPTAH //*[@id='password']
# XPATH //*[@id='password']/div[1]/div/div[1]/input
#password = browser.find_element_by_xpath("//*[@id='password']/div[1]/div/div[1]/input")
#password.send_keys(config['user']['password'])
element = WebDriverWait(browser, 10).until(
        EC.element_to_be_clickable((By.XPATH, "//*[@id='password']/div[1]/div/div[1]/input")))
element.send_keys(config['user']['password'])

主要成分是下面的区块

element = WebDriverWait(browser, 10).until(
        EC.element_to_be_clickable((By.XPATH, "//*[@id='password']/div[1]/div/div[1]/input")))
element.send_keys(config['user']['password'])

如果您提供 time.sleep(2) 它也应该与单行一起工作:

# Load Username
username = browser.find_element_by_id("identifierId")
username.send_keys(config['user']['name'])
time.sleep(2)

# Click Next
# Next Button ID XPATH //*[@id='identifierNext']/div/button/span
element = WebDriverWait(browser, 20).until(
        EC.element_to_be_clickable((By.ID, "identifierNext")))
element.click();

# Load Password
password = browser.find_element_by_xpath("//[@id='password']/div[1]/div/div[1]/input")
password.send_keys(config['user']['password'])

# Click Next
# Next Button XPATH //*[@id='passwordNext']/div/button/div[2]
# Full XPATH /html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[1]/div/form/span/section/div/div/div[1]/div[1]/div/div/div/div/div[1]/div/div[1]/input
element = WebDriverWait(browser, 20).until(
        EC.element_to_be_clickable((By.XPATH, "//*[@id='passwordNext']/div/button/div[2]")))
element.click();