Bài viết này sẽ mô tả cách triển khai tương tác PowerShell với API Google để thao túng người dùng G Suite.
Chúng tôi sử dụng một số dịch vụ nội bộ và đám mây trong toàn tổ chức. Phần lớn, việc ủy quyền trong đó thuộc về Google hoặc Active Directory, giữa chúng tôi không thể duy trì một bản sao; do đó, khi nhân viên mới rời đi, bạn cần tạo/kích hoạt tài khoản trong hai hệ thống này. Để tự động hóa quy trình, chúng tôi quyết định viết một tập lệnh thu thập thông tin và gửi nó đến cả hai dịch vụ.
Ủy quyền
Khi đưa ra các yêu cầu, chúng tôi quyết định sử dụng quản trị viên thực sự là con người để ủy quyền; điều này giúp đơn giản hóa việc phân tích các hành động trong trường hợp có những thay đổi lớn do vô tình hoặc cố ý.
Tôi đã chọn tập lệnh được sử dụng để ủy quyền trong các ứng dụng máy tính để bàn. Ngoài ra còn có một tùy chọn để sử dụng tài khoản dịch vụ mà không yêu cầu người dùng thực hiện các chuyển động không cần thiết.
Hình ảnh bên dưới là mô tả sơ đồ về kịch bản đã chọn từ trang Google.
Đầu tiên, chúng tôi gửi người dùng đến trang xác thực Tài khoản Google, chỉ định tham số GET:
id ứng dụng
các khu vực mà ứng dụng cần truy cập
địa chỉ mà người dùng sẽ được chuyển hướng đến sau khi hoàn tất thủ tục
cách chúng tôi sẽ cập nhật mã thông báo
Mã bảo mật
định dạng truyền mã xác minh
Sau khi ủy quyền hoàn tất, người dùng sẽ được chuyển hướng đến trang được chỉ định trong yêu cầu đầu tiên, với lỗi hoặc mã ủy quyền được truyền bởi tham số GET
Ứng dụng (tập lệnh) sẽ cần nhận các tham số này và nếu nhận được mã, hãy đưa ra yêu cầu sau để nhận mã thông báo
Nếu yêu cầu đúng, API Google sẽ trả về:
Mã thông báo truy cập mà chúng tôi có thể thực hiện yêu cầu
Thời hạn hiệu lực của mã thông báo này
Cần làm mới mã thông báo để làm mới mã thông báo Truy cập.
Trước tiên, bạn cần truy cập bảng điều khiển Google API: Thông tin xác thực - Bảng điều khiển API của Google, chọn ứng dụng mong muốn và trong phần Thông tin xác thực, hãy tạo mã định danh OAuth của ứng dụng khách. Ở đó (hoặc sau này, trong thuộc tính của mã định danh đã tạo), bạn cần chỉ định các địa chỉ được phép chuyển hướng. Trong trường hợp của chúng tôi, đây sẽ là một số mục localhost với các cổng khác nhau (xem bên dưới).
Để thuận tiện hơn khi đọc thuật toán tập lệnh, bạn có thể hiển thị các bước đầu tiên trong một hàm riêng biệt sẽ trả về mã thông báo Truy cập và làm mới cho ứng dụng:
Chúng tôi đặt ID khách hàng và Bí mật khách hàng thu được trong thuộc tính định danh khách hàng OAuth và trình xác minh mã là một chuỗi từ 43 đến 128 ký tự phải được tạo ngẫu nhiên từ các ký tự không được đặt trước: [AZ] / [az] / [0-9 ] / "-" / "." / "_" / "~".
Mã này sau đó sẽ được truyền lại. Nó loại bỏ lỗ hổng trong đó kẻ tấn công có thể chặn phản hồi được trả về dưới dạng chuyển hướng sau khi người dùng ủy quyền.
Bạn có thể gửi trình xác minh mã trong yêu cầu hiện tại ở dạng văn bản rõ ràng (điều này khiến nó vô nghĩa - điều này chỉ phù hợp với các hệ thống không hỗ trợ SHA256) hoặc bằng cách tạo hàm băm bằng thuật toán SHA256, phải được mã hóa trong BASE64Url (khác nhau từ Base64 bằng hai ký tự bảng) và xóa phần cuối dòng ký tự: =.
Tiếp theo, chúng ta cần bắt đầu nghe http trên máy cục bộ để nhận được phản hồi sau khi ủy quyền, phản hồi này sẽ được trả về dưới dạng chuyển hướng.
Các tác vụ quản trị được thực hiện trên một máy chủ đặc biệt, chúng tôi không thể loại trừ khả năng một số quản trị viên sẽ chạy tập lệnh cùng lúc, do đó nó sẽ chọn ngẫu nhiên một cổng cho người dùng hiện tại, nhưng tôi đã chỉ định các cổng được xác định trước vì chúng cũng phải được thêm dưới dạng đáng tin cậy trong bảng điều khiển API.
access_type = ngoại tuyến có nghĩa là ứng dụng có thể tự cập nhật mã thông báo đã hết hạn mà không cần người dùng tương tác với trình duyệt, response_type = code đặt định dạng về cách trả về mã (tham chiếu đến phương thức ủy quyền cũ, khi người dùng sao chép mã từ trình duyệt vào tập lệnh), phạm vi cho biết phạm vi và loại quyền truy cập. Chúng phải được phân tách bằng dấu cách hoặc %20 (theo Mã hóa URL). Bạn có thể xem danh sách các khu vực truy cập với các loại tại đây: Phạm vi OAuth 2.0 cho API Google.
Sau khi nhận được mã ủy quyền, ứng dụng sẽ trả về thông báo đóng cho trình duyệt, ngừng nghe trên cổng và gửi yêu cầu POST để lấy mã thông báo. Chúng tôi chỉ ra trong đó id và bí mật được chỉ định trước đó từ API bảng điều khiển, địa chỉ mà người dùng sẽ được chuyển hướng và Grant_type theo đặc tả giao thức.
Đáp lại, chúng tôi sẽ nhận được mã thông báo Access, thời hạn hiệu lực của nó tính bằng giây và mã thông báo Làm mới để chúng tôi có thể cập nhật mã thông báo Access.
Ứng dụng phải lưu trữ mã thông báo ở nơi an toàn với thời hạn sử dụng lâu dài, vì vậy cho đến khi chúng tôi thu hồi quyền truy cập đã nhận, ứng dụng sẽ không trả lại mã thông báo làm mới. Cuối cùng, tôi đã thêm yêu cầu thu hồi mã thông báo; nếu ứng dụng không được hoàn thành thành công và mã thông báo làm mới không được trả về, nó sẽ bắt đầu lại quy trình (chúng tôi cho rằng việc lưu trữ mã thông báo cục bộ trên thiết bị đầu cuối là không an toàn và chúng tôi không không muốn phức tạp hóa mọi thứ bằng mật mã hoặc mở trình duyệt thường xuyên).
Như bạn đã nhận thấy, khi thu hồi mã thông báo, Invoke-WebRequest sẽ được sử dụng. Không giống như Invoke-RestMethod, nó không trả về dữ liệu đã nhận ở định dạng có thể sử dụng được và hiển thị trạng thái của yêu cầu.
Tiếp theo, tập lệnh yêu cầu bạn nhập họ và tên của người dùng, tạo thông tin đăng nhập + email.
yêu cầu
Các yêu cầu tiếp theo sẽ là - trước hết, bạn cần kiểm tra xem người dùng có cùng thông tin đăng nhập đã tồn tại hay chưa để đưa ra quyết định tạo một yêu cầu mới hay kích hoạt yêu cầu hiện tại.
Tôi quyết định triển khai tất cả các yêu cầu ở định dạng của một hàm bằng một lựa chọn, sử dụng switch:
Trong mỗi yêu cầu, bạn cần gửi tiêu đề Ủy quyền chứa loại mã thông báo và chính mã thông báo Truy cập. Hiện tại, loại mã thông báo luôn là Bearer. Bởi vì chúng tôi cần kiểm tra xem mã thông báo chưa hết hạn và cập nhật mã thông báo sau một giờ kể từ thời điểm mã thông báo được phát hành, tôi đã chỉ định yêu cầu cho một chức năng khác trả về mã thông báo Access. Đoạn mã tương tự nằm ở đầu tập lệnh khi nhận mã thông báo Truy cập đầu tiên:
Yêu cầu email:$query sẽ yêu cầu API tìm kiếm người dùng có chính xác email đó, bao gồm cả bí danh. Bạn cũng có thể sử dụng ký tự đại diện: =, :, :{PREFIX}*.
Để lấy dữ liệu, hãy sử dụng phương thức yêu cầu GET, để chèn dữ liệu (tạo tài khoản hoặc thêm thành viên vào nhóm) - POST, để cập nhật dữ liệu hiện có - PUT, để xóa bản ghi (ví dụ: thành viên khỏi nhóm) - XÓA BỎ.
Tập lệnh cũng sẽ yêu cầu số điện thoại (một chuỗi chưa được xác thực) và đưa vào nhóm phân phối khu vực. Nó quyết định đơn vị tổ chức nào mà người dùng nên có dựa trên OU Active Directory đã chọn và đưa ra mật khẩu:
do {
$phone = Read-Host "Телефон в формате +7хххххххх"
} while (-not $phone)
do {
$moscow = Read-Host "В Московский офис? (y/n) "
} while (-not (($moscow -eq 'y') -or ($moscow -eq 'n')))
$orgunit = '/'
if ($OU -like "*OU=Delivery,OU=Users,OU=ROOT,DC=rocket,DC=local") {
Write-host "Будет создана в /Team delivery"
$orgunit = "/Team delivery"
}
$Password = -join ( 48..57 + 65..90 + 97..122 | Get-Random -Count 12 | % {[char]$_})+"*Ba"
Và sau đó anh ta bắt đầu thao túng tài khoản:
$query = @{
email = $email
givenName = $firstname
familyName = $lastname
password = $password
phone = $phone
orgunit = $orgunit
}
if ($GMailExist) {
Write-Host "Запускаем изменение аккаунта" -f mag
(GoogleQuery 'UpdateAccount' $query) | fl
write-host "Не забудь проверить группы у включенного $Username в Google."
} else {
Write-Host "Запускаем создание аккаунта" -f mag
(GoogleQuery 'CreateAccount' $query) | fl
}
if ($moscow -eq "y"){
write-host "Добавляем в группу moscowoffice"
$query = @{
groupkey = '[email protected]'
email = $email
}
(GoogleQuery 'AddMember' $query) | fl
}
Các chức năng cập nhật và tạo tài khoản có cú pháp tương tự; không yêu cầu tất cả các trường bổ sung; trong phần có số điện thoại, bạn cần chỉ định một mảng có thể chứa tối đa một bản ghi có số và loại của nó.
Để không gặp lỗi khi thêm người dùng vào nhóm, trước tiên chúng tôi có thể kiểm tra xem người dùng đó đã là thành viên của nhóm này hay chưa bằng cách lấy danh sách thành viên nhóm hoặc thành phần từ chính người dùng đó.
Truy vấn tư cách thành viên nhóm của một người dùng cụ thể sẽ không đệ quy và sẽ chỉ hiển thị tư cách thành viên trực tiếp. Việc đưa người dùng vào nhóm chính đã có nhóm con mà người dùng đó là thành viên sẽ thành công.
Kết luận
Tất cả những gì còn lại là gửi cho người dùng mật khẩu của tài khoản mới. Chúng tôi thực hiện việc này thông qua SMS và gửi thông tin chung kèm theo hướng dẫn và đăng nhập vào email cá nhân, cùng với số điện thoại do bộ phận tuyển dụng cung cấp. Ngoài ra, bạn có thể tiết kiệm tiền và gửi mật khẩu của mình đến một cuộc trò chuyện điện tín bí mật, đây cũng có thể được coi là yếu tố thứ hai (MacBook sẽ là một ngoại lệ).
Cảm ơn bạn đã đọc đến cuối. Tôi sẽ rất vui khi thấy những gợi ý để cải thiện phong cách viết bài và chúc bạn ít mắc lỗi hơn khi viết script =)
Danh sách các liên kết có thể hữu ích theo chủ đề hoặc chỉ đơn giản là trả lời các câu hỏi: