Compare commits

...

27 Commits

Author SHA1 Message Date
Jay Lee
30069d3039 Update build.yml 2022-10-12 12:00:07 -04:00
Jay Lee
3ef8a5a762 Update var.py 2022-10-12 08:10:38 -04:00
Jay Lee
b12fda5007 Update build.yml 2022-10-11 17:15:03 -04:00
Jay Lee
26925c30c1 Update build.yml 2022-10-07 11:40:59 -04:00
Jay Lee
4085816fa3 Update build.yml 2022-10-07 10:52:12 -04:00
Jay Lee
7e36e5abe6 Update build.yml 2022-10-07 10:23:26 -04:00
Jay Lee
2037189148 Update build.yml 2022-10-07 08:13:43 -04:00
Jay Lee
c7781e66e1 Update build.yml 2022-10-06 22:18:30 -04:00
Jay Lee
8843675ad4 leave Homebrew in place 2022-10-06 22:47:35 +00:00
Jay Lee
c05a1ea6b4 Honor nobrowser.txt on auth 2022-10-06 22:36:25 +00:00
Jay Lee
d9a5ac849b try again with new creds 2022-10-06 17:45:05 +00:00
Jay Lee
51d4c29dd5 update creds 2022-10-06 17:38:01 +00:00
Jay Lee
c2bb9cbdaf Catch revoke and throw nicer error 2022-10-05 17:09:39 +00:00
Lewis Lebentz
d185765831 Add Frontline Worker alias (#1566) 2022-10-05 12:40:53 -04:00
Jay Lee
f57f311f16 Update build.yml 2022-09-27 07:07:21 -04:00
Jay Lee
4c81849c60 Update build.yml 2022-09-26 16:28:42 -04:00
Jay Lee
156c8319d9 Update build.yml 2022-09-26 14:20:54 -04:00
Jay Lee
b8de3310d0 Update build.yml 2022-09-26 13:53:29 -04:00
Jay Lee
f28cf664cb Update build.yml 2022-09-26 13:46:14 -04:00
Jay Lee
02b876155a Allow 'info domain' for delegate admins 2022-09-15 20:03:03 +00:00
Jay Lee
97bd1f71c3 Merge branch 'main' of https://github.com/GAM-team/GAM 2022-09-15 14:46:53 +00:00
Jay Lee
8be4445f0d Fix crm org retrieval 2022-09-15 14:45:02 +00:00
Jay Lee
550cf47db4 Update reports.py 2022-09-15 10:22:29 -04:00
Jay Lee
05d32eec08 Update __init__.py 2022-09-14 19:17:04 -04:00
Jay Lee
59c181eeda Update __init__.py 2022-09-14 19:07:58 -04:00
Jay Lee
dd5fd2a2c3 Update __init__.py 2022-09-14 18:02:59 -04:00
Jay Lee
6ab8fbf538 test with lowmemory.txt 2022-09-14 17:49:40 -04:00
10 changed files with 107 additions and 77 deletions

Binary file not shown.

BIN
.github/actions/creds.tar.xz.gpg vendored Normal file

Binary file not shown.

View File

@@ -29,7 +29,7 @@ jobs:
goal: build
arch: x86_64
openssl_archs: linux-x86_64
- os: [self-hosted, linux, arm64]
- os: [self-hosted, linux, arm64, gcp]
jid: 2
goal: build
arch: aarch64
@@ -84,7 +84,7 @@ jobs:
with:
path: |
bin.tar.xz
key: gam-${{ matrix.jid }}-20220907
key: gam-${{ matrix.jid }}-20221012
- name: Untar Cache archive
if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit == 'true'
@@ -125,11 +125,11 @@ jobs:
sudo apt-get -qq --yes update
sudo apt-get -qq --yes install swig libpcsclite-dev
- name: MacOS remove Homebrew
if: runner.os == 'macOS'
run: |
# remove everything except the libraries needed by yubikey-manager
brew uninstall $(brew list | grep -v 'pcre\|swig\|pcsc-lite')
#- name: MacOS remove Homebrew
# if: runner.os == 'macOS'
# run: |
# # remove everything except the libraries needed by yubikey-manager
# brew uninstall $(brew list | grep -v 'pcre\|swig\|pcsc-lite')
- name: MacOS install tools
if: runner.os == 'macOS'
@@ -200,7 +200,6 @@ jobs:
echo "PYBUILDRELEASE_ARCH=${PYBUILDRELEASE_ARCH}" >> $GITHUB_ENV
echo "openssl_archs=${openssl_archs}" >> $GITHUB_ENV
echo "LD_LIBRARY_PATH=${OPENSSL_INSTALL_PATH}/lib:${PYTHON_INSTALL_PATH}/lib" >> $GITHUB_ENV
#echo "PATH=${PATH}:${PYTHON_INSTALL_PATH}/scripts" >> $GITHUB_ENV
- name: Get latest stable OpenSSL source
if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit != 'true'
@@ -373,6 +372,9 @@ jobs:
Copy-Item -Path "${env:PYTHON_SOURCE_PATH}\Lib\*" "${env:PYTHON_INSTALL_PATH}\lib\" -recurse
Copy-Item -Path "${env:PYTHON_SOURCE_PATH}\Include\*" "${env:PYTHON_INSTALL_PATH}\include\" -recurse
Copy-Item -Path "${env:PYTHON_SOURCE_PATH}\PC\*.h" "${env:PYTHON_INSTALL_PATH}\include\"
$env:Path = '${PYTHON_INSTALL_PATH}/bin' + $env:Path
echo "Path=$env:Path" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
echo "PATH: ${env:Path}"
- name: Mac/Linux Build Python
if: matrix.goal == 'build' && runner.os != 'Windows' && steps.cache-python-ssl.outputs.cache-hit != 'true'
@@ -387,6 +389,9 @@ jobs:
cd "${PYTHON_SOURCE_PATH}"
$MAKE altinstall
$MAKE bininstall
export PATH="${PATH}:${PYTHON_INSTALL_PATH}/bin"
echo "PATH=${PATH}" >> $GITHUB_ENV
echo "PATH: ${PATH}"
- name: Run Python
run: |
@@ -399,25 +404,6 @@ jobs:
"${PYTHON}" -m pip install --upgrade pip
"${PYTHON}" -m pip install --upgrade wheel
"${PYTHON}" -m pip install --upgrade setuptools
- name: Install PyInstaller
if: matrix.goal == 'build'
run: |
git clone https://github.com/pyinstaller/pyinstaller.git
cd pyinstaller
export latest_release=$(git tag --list | grep -v dev | grep -v rc | sort -Vr | head -n1)
git checkout "${latest_release}"
# remove pre-compiled bootloaders so we fail if bootloader compile fails
rm -rvf PyInstaller/bootloader/*-*/*
cd bootloader
if [[ "${arch}" == "Win32" ]]; then
export PYINSTALLER_BUILD_ARGS="--target-arch=32bit"
fi
echo "PyInstaller build arguments: ${PYINSTALLER_BUILD_ARGS}"
"${PYTHON}" ./waf all $PYINSTALLER_BUILD_ARGS
cd ../..
echo "---- Installing PyInstaller ----"
"${PYTHON}" -m pip install pyinstaller
- name: Install pip requirements
run: |
@@ -437,6 +423,27 @@ jobs:
"${PYTHON}" -m pip install --upgrade -r requirements.txt ${PIP_ARGS}
"${PYTHON}" -m pip list
- name: Install PyInstaller
if: matrix.goal == 'build'
run: |
git clone https://github.com/pyinstaller/pyinstaller.git
cd pyinstaller
export latest_release=$(git tag --list | grep -v dev | grep -v rc | sort -Vr | head -n1)
# temp freeze PyInstaller at 5.3
export latest_release="v5.3"
git checkout "${latest_release}"
# remove pre-compiled bootloaders so we fail if bootloader compile fails
rm -rvf PyInstaller/bootloader/*-*/*
cd bootloader
if [[ "${arch}" == "Win32" ]]; then
export PYINSTALLER_BUILD_ARGS="--target-arch=32bit"
fi
echo "PyInstaller build arguments: ${PYINSTALLER_BUILD_ARGS}"
"${PYTHON}" ./waf all $PYINSTALLER_BUILD_ARGS
cd ..
echo "---- Installing PyInstaller ----"
"${PYTHON}" -m pip install .
- name: Build GAM with PyInstaller
if: matrix.goal != 'test'
run: |
@@ -553,11 +560,12 @@ jobs:
if [[ "${RUNNER_OS}" == "macOS" ]]; then
brew install gnupg
fi
source ../.github/actions/decrypt.sh ../.github/actions/creds.tar.gpg creds.tar
source ../.github/actions/decrypt.sh ../.github/actions/creds.tar.xz.gpg creds.tar.xz
export OAUTHFILE="oauth2.txt-gam-gha-${JID}"
echo "OAUTHFILE=${OAUTHFILE}" >> $GITHUB_ENV
export gam_user="gam-gha-${JID}@pdl.jaylee.us"
echo "gam_user=${gam_user}" >> $GITHUB_ENV
touch "${gampath}/lowmemory.txt"
$gam checkconn
$gam oauth info
$gam info domain
@@ -736,12 +744,19 @@ jobs:
- name: Download artifacts
uses: actions/download-artifact@v3
- name: Set datetime version string
id: dateversion
run: |
echo "::set-output name=dateversion::$(date +'%Y%m%d.%k%M%S')"
- name: VirusTotal Scan
uses: crazy-max/ghaction-virustotal@v3
with:
vt_api_key: ${{ secrets.VT_API_KEY }}
files: |
gam-binaries/*
- uses: "marvinpinto/action-automatic-releases@latest"
name: Publish draft release
with:

View File

@@ -556,7 +556,9 @@ def SetGlobalVariables():
_getOldSignalFile(GC_LOW_MEMORY, 'lowmemory.txt')
_getOldSignalFile(GC_NO_BROWSER, 'nobrowser.txt')
_getOldSignalFile(GC_NO_TDEMAIL, 'notdemail.txt')
_getOldSignalFile(GC_OAUTH_BROWSER, 'oauthbrowser.txt')
# oauthbrowser.txt is deprecated as we now always
# use the localhost flow.
#_getOldSignalFile(GC_OAUTH_BROWSER, 'oauthbrowser.txt')
# _getOldSignalFile(GC_NO_CACHE, u'nocache.txt')
# _getOldSignalFile(GC_CACHE_DISCOVERY_ONLY, u'allcache.txt', filePresentValue=False, fileAbsentValue=True)
_getOldSignalFile(GC_NO_CACHE,
@@ -7130,7 +7132,7 @@ def getCRMService(login_hint):
scopes,
'online',
login_hint=login_hint,
use_console_flow=not GC_Values[GC_OAUTH_BROWSER])
open_browser=not GC_Values[GC_NO_BROWSER])
httpc = transport.AuthorizedHttp(creds, transport.create_http())
return getService('cloudresourcemanager', httpc), httpc
@@ -10544,7 +10546,7 @@ def doRequestOAuth(login_hint=None, scopes=None):
access_type='offline',
login_hint=login_hint,
credentials_file=GC_Values[GC_OAUTH2_TXT],
use_console_flow=not GC_Values[GC_OAUTH_BROWSER])
open_browser=not GC_Values[GC_NO_BROWSER])
creds.write()
except gam.auth.oauth.InvalidClientSecretsFileError:
controlflow.system_error_exit(14, missing_client_secrets_message)

View File

@@ -272,6 +272,7 @@ class Credentials(google.oauth2.credentials.Credentials):
access_type='offline',
login_hint=None,
filename=None,
open_browser=True,
use_console_flow=False):
"""Runs an OAuth Flow from client secrets to generate credentials.
@@ -291,8 +292,11 @@ class Credentials(google.oauth2.credentials.Credentials):
login_hint: String, The email address that will be displayed on the Google
login page as a hint for the user to login to the correct account.
filename: String, the path to a file to use to save the credentials.
use_console_flow: Boolean, True if the authentication flow should be run
strictly from a console; False to launch a browser for authentication.
use_console_flow: OBSOLETE: Boolean, True if the authentication flow
should be run strictly from a console; False to launch a browser
for authentication.
open_browser: Boolean: whether or not GAM should try to open the browser
automatically.
Returns:
Credentials
@@ -312,12 +316,11 @@ class Credentials(google.oauth2.credentials.Credentials):
flow = _ShortURLFlow.from_client_config(client_config,
scopes,
autogenerate_code_verifier=True)
flow_kwargs = {'access_type': access_type}
flow_kwargs = {'access_type': access_type,
'open_browser': open_browser}
if login_hint:
flow_kwargs['login_hint'] = login_hint
flow.run_dual(use_console_flow,
**flow_kwargs)
flow.run_dual(**flow_kwargs)
return cls.from_google_oauth2_credentials(flow.credentials,
filename=filename)
@@ -328,6 +331,7 @@ class Credentials(google.oauth2.credentials.Credentials):
access_type='offline',
login_hint=None,
credentials_file=None,
open_browser=True,
use_console_flow=False):
"""Runs an OAuth Flow from secrets stored on disk to generate credentials.
@@ -348,8 +352,11 @@ class Credentials(google.oauth2.credentials.Credentials):
login page as a hint for the user to login to the correct account.
credentials_file: String, the path to a file to use to save the
credentials.
use_console_flow: Boolean, True if the authentication flow should be run
strictly from a console; False to launch a browser for authentication.
use_console_flow: OBSOLETE: Boolean, True if the authentication flow
should be run strictly from a console; False to launch a browser for
authentication.
open_browser: Boolean, whether or not GAM should try to open the browser
directly.
Raises:
InvalidClientSecretsFileError: If the client secrets file cannot be
@@ -378,14 +385,13 @@ class Credentials(google.oauth2.credentials.Credentials):
raise InvalidClientSecretsFileFormatError(
f'Could not extract Client ID or Client Secret from file {client_secrets_file}'
)
return cls.from_client_secrets(client_id,
client_secret,
scopes,
access_type=access_type,
login_hint=login_hint,
filename=credentials_file,
use_console_flow=use_console_flow)
open_browser=open_browser)
def _fetch_id_token_data(self):
"""Fetches verification details from Google for the OAuth2.0 token.
@@ -482,7 +488,11 @@ class Credentials(google.oauth2.credentials.Credentials):
def _locked_refresh(self, request):
"""Refreshes the credential's access token while the file lock is held."""
assert self._lock.is_locked
super().refresh(request)
try:
super().refresh(request)
except google.auth.exceptions.RefreshError as e:
controlflow.system_error_exit(9, str(e))
def write(self):
"""Writes credentials to disk."""
@@ -595,7 +605,6 @@ class _ShortURLFlow(google_auth_oauthlib.flow.InstalledAppFlow):
def run_dual(self,
use_console_flow,
authorization_prompt_message='',
console_prompt_message='',
web_success_message='',
@@ -605,7 +614,7 @@ class _ShortURLFlow(google_auth_oauthlib.flow.InstalledAppFlow):
mgr = multiprocessing.Manager()
d = mgr.dict()
d['trailing_slash'] = redirect_uri_trailing_slash
d['open_browser'] = use_console_flow
d['open_browser'] = open_browser
http_client = multiprocessing.Process(target=_wait_for_http_client,
args=(d,))
user_input = multiprocessing.Process(target=_wait_for_user_input,

View File

@@ -339,9 +339,10 @@ def get_all_pages(service,
else:
kwargs.update(page_key)
if GC_Values[GC_LOW_MEMORY]:
tempdir = TemporaryDirectory(
prefix='GAM-',
ignore_cleanup_errors=True)
td_args = {'prefix': 'GAM-'}
if sys.version_info.minor >= 10:
td_args['ignore_cleanup_errors'] = True
tempdir = TemporaryDirectory(**td_args)
tempfile = os.path.join(tempdir.name, 'gapi_pages')
all_items = shelve.open(tempfile)
# attach tempdir to all_items so we

View File

@@ -13,12 +13,14 @@ def get_org_id():
gapi_directory_customer.setTrueCustomerId()
crm = build()
query = f'directorycustomerid:{GC_Values[GC_CUSTOMER_ID]}'
orgs = gapi.get_all_pages(crm.organizations(),
results = gapi.call(crm.organizations(),
'search',
'organizations',
pageSize=1,
fields='organizations/name',
query=query)
if len(orgs) < 1:
orgs = results.get('organizations')
if not orgs:
# return nothing and let calling API deal with it
# since caller knows what GCP role would serve best
return
return orgs[0]['name']
return orgs[0].get('name')

View File

@@ -21,36 +21,36 @@ def doGetCustomerInfo():
'get',
customerKey=customer_id)
print(f'Customer ID: {customer_info["id"]}')
print(f'Primary Domain: {customer_info["customerDomain"]}')
fields = 'domains(creationTime,domainName,isPrimary,verified)'
try:
result = gapi.call(
domains = gapi.call(
cd.domains(),
'get',
'list',
fields=fields,
customer=customer_id,
domainName=customer_info['customerDomain'],
fields='verified',
throw_reasons=[gapi.errors.ErrorReason.DOMAIN_NOT_FOUND])
throw_reasons=[gapi.errors.ErrorReason.DOMAIN_NOT_FOUND]).get('domains', [])
for domain in domains:
if domain.get('isPrimary'):
primary_domain = domain
break
else:
primary_domain = {}
except gapi.errors.GapiDomainNotFoundError:
result = {'verified': False}
print(f'Primary Domain Verified: {result["verified"]}')
# If customer has changed primary domain customerCreationTime is date
# of current primary being added, not customer create date.
# We should also get all domains and use oldest date
customer_creation = customer_info['customerCreationTime']
date_format = '%Y-%m-%dT%H:%M:%S.%fZ'
oldest = datetime.datetime.strptime(customer_creation, date_format)
domains = gapi.get_items(cd.domains(),
'list',
'domains',
customer=customer_id,
fields='domains(creationTime)')
primary_domain = {}
print(f'Primary Domain: {primary_domain.get("domainName", "Unknown")}')
print(f'Primary Domain Verified: {primary_domain.get("verified", "Unknown")}')
# we'll assume creation time is time of oldest domain customer has
oldest = 'Unknown'
for domain in domains:
creation_timestamp = int(domain['creationTime']) / 1000
domain_creation = datetime.datetime.fromtimestamp(creation_timestamp)
if domain_creation < oldest:
if oldest == 'Unknown' or domain_creation < oldest:
oldest = domain_creation
print(f'Customer Creation Time: {oldest.strftime(date_format)}')
customer_language = customer_info.get('language', 'Unset (defaults to en)')
if oldest != 'Unknown':
date_format = '%Y-%m-%dT%H:%M:%S.%fZ'
oldest = oldest.strftime(date_format)
print(f'Customer Creation Time: {oldest}')
customer_language = customer_info.get('language', 'Unset or Unknown (defaults to en)')
print(f'Default Language: {customer_language}')
if 'postalAddress' in customer_info:
print('Address:')
@@ -59,7 +59,7 @@ def doGetCustomerInfo():
print(f' {field}: {customer_info["postalAddress"][field]}')
if 'phoneNumber' in customer_info:
print(f'Phone: {customer_info["phoneNumber"]}')
print(f'Admin Secondary Email: {customer_info["alternateEmail"]}')
print(f'Admin Secondary Email: {customer_info.get("alternateEmail", "Unknown")}')
user_counts_map = {
'accounts:num_users': 'Total Users',
'accounts:gsuite_basic_total_licenses': 'G Suite Basic Licenses',

View File

@@ -426,6 +426,7 @@ def showReport():
titles = ['name', 'value', 'client_id']
csvRows = []
auth_apps = list()
usage = list(usage)
for item in usage[0]['parameters']:
if 'name' not in item:
continue

View File

@@ -8,7 +8,7 @@ import platform
import re
GAM_AUTHOR = 'Jay Lee <jay0lee@gmail.com>'
GAM_VERSION = '6.25'
GAM_VERSION = '6.26'
GAM_LICENSE = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
GAM_URL = 'https://jaylee.us/gam'
@@ -206,7 +206,7 @@ SKUS = {
},
'1010020030': {
'product': 'Google-Apps',
'aliases': ['workspacefrontline', 'workspacefrontlineworker'],
'aliases': ['wsflw', 'workspacefrontline', 'workspacefrontlineworker'],
'displayName': 'Workspace Frontline'
},
'1010340002': {