saas-security-posture
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSaaS Security Posture Management for Startups
初创企业SaaS安全态势管理
Secure every SaaS tool your company relies on with practical, command-driven hardening.
通过实用的命令驱动型强化方案,保护公司依赖的每一款SaaS工具。
1. When to Use This Skill
1. 何时使用此技能
- SOC 2 preparation — auditors need evidence of MFA, access controls, and OAuth governance.
- Suspicious OAuth app — an employee authorized a third-party app with broad scopes.
- SaaS sprawl — teams sign up for tools with company email and nobody tracks them.
- Post-incident hardening — after phishing or credential leaks, tighten every surface.
- SOC 2 合规准备 — 审计人员需要MFA、访问控制和OAuth治理的相关证据。
- 可疑OAuth应用 — 员工授权了一个权限范围广泛的第三方应用。
- SaaS工具蔓延 — 团队使用公司邮箱注册工具,但无人追踪管理。
- 事件后强化 — 遭遇钓鱼攻击或凭证泄露后,全面收紧安全防护。
2. SaaS Inventory Audit
2. SaaS资产审计
Google Workspace — OAuth Grants
Google Workspace — OAuth授权
bash
gam all users show tokens > oauth_tokens_audit.csvbash
gam all users show tokens > oauth_tokens_audit.csvGitHub — Installed Apps
GitHub — 已安装应用
bash
gh api /orgs/{ORG}/installations --paginate \
--jq '.installations[] | {app: .app_slug, permissions: .permissions, created: .created_at}'
gh api /orgs/{ORG}/credential-authorizations --paginate \
--jq '.[] | {login: .login, credential_type: .credential_type}'bash
gh api /orgs/{ORG}/installations --paginate \
--jq '.installations[] | {app: .app_slug, permissions: .permissions, created: .created_at}'
gh api /orgs/{ORG}/credential-authorizations --paginate \
--jq '.[] | {login: .login, credential_type: .credential_type}'Slack — Approved and Pending Apps
Slack — 已批准和待审批应用
bash
curl -s -H "Authorization: Bearer ${SLACK_ADMIN_TOKEN}" \
"https://slack.com/api/admin.apps.approved.list" | jq '.approved_apps[] | {name: .app.name, id: .app.id}'
curl -s -H "Authorization: Bearer ${SLACK_ADMIN_TOKEN}" \
"https://slack.com/api/admin.apps.requests.list" | jq '.app_requests[]'bash
curl -s -H "Authorization: Bearer ${SLACK_ADMIN_TOKEN}" \
"https://slack.com/api/admin.apps.approved.list" | jq '.approved_apps[] | {name: .app.name, id: .app.id}'
curl -s -H "Authorization: Bearer ${SLACK_ADMIN_TOKEN}" \
"https://slack.com/api/admin.apps.requests.list" | jq '.app_requests[]'AWS — IAM Credential Report
AWS — IAM凭证报告
bash
aws iam generate-credential-report
aws iam get-credential-report --output text --query 'Content' | base64 -d > iam_credential_report.csvbash
aws iam generate-credential-report
aws iam get-credential-report --output text --query 'Content' | base64 -d > iam_credential_report.csvMaster Inventory Template
主资产清单模板
yaml
tools:
- name: Google Workspace
owner: it@company.com
sso: true
mfa: enforced
- name: GitHub Enterprise
owner: engineering@company.com
sso: true
mfa: enforced
- name: Slack Business+
owner: it@company.com
sso: true
app_approval: required
- name: AWS Organizations
owner: platform@company.com
sso: true
scp_enforced: trueyaml
tools:
- name: Google Workspace
owner: it@company.com
sso: true
mfa: enforced
- name: GitHub Enterprise
owner: engineering@company.com
sso: true
mfa: enforced
- name: Slack Business+
owner: it@company.com
sso: true
app_approval: required
- name: AWS Organizations
owner: platform@company.com
sso: true
scp_enforced: true3. GitHub Security Hardening
3. GitHub安全强化
bash
undefinedbash
undefinedEnforce 2FA and find non-compliant members
强制启用2FA并找出不合规成员
gh api -X PATCH /orgs/{ORG} -f two_factor_requirement_enabled=true
gh api /orgs/{ORG}/members?filter=2fa_disabled --paginate --jq '.[].login'
gh api -X PATCH /orgs/{ORG} -f two_factor_requirement_enabled=true
gh api /orgs/{ORG}/members?filter=2fa_disabled --paginate --jq '.[].login'
Verify SAML SSO identities
验证SAML SSO身份
gh api /orgs/{ORG}/credential-authorizations --paginate
--jq '.[] | {login: .login, saml_name_id: .saml_name_id}'
--jq '.[] | {login: .login, saml_name_id: .saml_name_id}'
gh api /orgs/{ORG}/credential-authorizations --paginate
--jq '.[] | {login: .login, saml_name_id: .saml_name_id}'
--jq '.[] | {login: .login, saml_name_id: .saml_name_id}'
Add IP allow list entry
添加IP允许列表条目
gh api -X POST /orgs/{ORG}/ip-allow-list
-f allow_list_value="203.0.113.0/24" -f name="Office VPN" -F is_active=true
-f allow_list_value="203.0.113.0/24" -f name="Office VPN" -F is_active=true
gh api -X POST /orgs/{ORG}/ip-allow-list
-f allow_list_value="203.0.113.0/24" -f name="Office VPN" -F is_active=true
-f allow_list_value="203.0.113.0/24" -f name="Office VPN" -F is_active=true
Branch protection on main
主分支保护
gh api -X PUT /repos/{ORG}/{REPO}/branches/main/protection
-H "Accept: application/vnd.github+json" --input - <<'EOF' { "required_status_checks": {"strict": true, "contexts": ["ci/build","ci/test"]}, "enforce_admins": true, "required_pull_request_reviews": { "required_approving_review_count": 2, "dismiss_stale_reviews": true, "require_code_owner_reviews": true }, "restrictions": null, "allow_force_pushes": false, "allow_deletions": false } EOF
-H "Accept: application/vnd.github+json" --input - <<'EOF' { "required_status_checks": {"strict": true, "contexts": ["ci/build","ci/test"]}, "enforce_admins": true, "required_pull_request_reviews": { "required_approving_review_count": 2, "dismiss_stale_reviews": true, "require_code_owner_reviews": true }, "restrictions": null, "allow_force_pushes": false, "allow_deletions": false } EOF
gh api -X PUT /repos/{ORG}/{REPO}/branches/main/protection
-H "Accept: application/vnd.github+json" --input - <<'EOF' { "required_status_checks": {"strict": true, "contexts": ["ci/build","ci/test"]}, "enforce_admins": true, "required_pull_request_reviews": { "required_approving_review_count": 2, "dismiss_stale_reviews": true, "require_code_owner_reviews": true }, "restrictions": null, "allow_force_pushes": false, "allow_deletions": false } EOF
-H "Accept: application/vnd.github+json" --input - <<'EOF' { "required_status_checks": {"strict": true, "contexts": ["ci/build","ci/test"]}, "enforce_admins": true, "required_pull_request_reviews": { "required_approving_review_count": 2, "dismiss_stale_reviews": true, "require_code_owner_reviews": true }, "restrictions": null, "allow_force_pushes": false, "allow_deletions": false } EOF
Audit PATs and revoke stale tokens
审计PAT并撤销过期令牌
gh api /orgs/{ORG}/personal-access-tokens --paginate
--jq '.[] | {owner: .owner.login, name: .token_name, expires: .token_expires_at}' gh api -X DELETE /orgs/{ORG}/personal-access-tokens/{PAT_ID}
--jq '.[] | {owner: .owner.login, name: .token_name, expires: .token_expires_at}' gh api -X DELETE /orgs/{ORG}/personal-access-tokens/{PAT_ID}
gh api /orgs/{ORG}/personal-access-tokens --paginate
--jq '.[] | {owner: .owner.login, name: .token_name, expires: .token_expires_at}' gh api -X DELETE /orgs/{ORG}/personal-access-tokens/{PAT_ID}
--jq '.[] | {owner: .owner.login, name: .token_name, expires: .token_expires_at}' gh api -X DELETE /orgs/{ORG}/personal-access-tokens/{PAT_ID}
Audit deploy keys and webhooks
审计部署密钥和Webhook
for repo in $(gh repo list {ORG} --limit 500 --json name -q '.[].name'); do
gh api /repos/{ORG}/${repo}/keys --jq '.[] | {title: .title, read_only: .read_only}'
done
gh api /orgs/{ORG}/hooks --jq '.[] | {url: .config.url, events: .events, active: .active}'
---for repo in $(gh repo list {ORG} --limit 500 --json name -q '.[].name'); do
gh api /repos/{ORG}/${repo}/keys --jq '.[] | {title: .title, read_only: .read_only}'
done
gh api /orgs/{ORG}/hooks --jq '.[] | {url: .config.url, events: .events, active: .active}'
---4. Slack Security
4. Slack安全配置
bash
undefinedbash
undefinedRequire app approval
启用应用审批要求
curl -s -X POST -H "Authorization: Bearer ${SLACK_ADMIN_TOKEN}"
-H "Content-Type: application/json"
"https://slack.com/api/admin.apps.config.set" -d '{"app_approval_enabled": true}'
-H "Content-Type: application/json"
"https://slack.com/api/admin.apps.config.set" -d '{"app_approval_enabled": true}'
curl -s -X POST -H "Authorization: Bearer ${SLACK_ADMIN_TOKEN}"
-H "Content-Type: application/json"
"https://slack.com/api/admin.apps.config.set" -d '{"app_approval_enabled": true}'
-H "Content-Type: application/json"
"https://slack.com/api/admin.apps.config.set" -d '{"app_approval_enabled": true}'
Set workspace to invite-only
将工作区设置为仅邀请模式
curl -s -X POST -H "Authorization: Bearer ${SLACK_ADMIN_TOKEN}"
-H "Content-Type: application/json"
"https://slack.com/api/admin.teams.settings.setDiscoverability"
-d '{"team_id": "T0XXXXXXX", "discoverability": "invite_only"}'
-H "Content-Type: application/json"
"https://slack.com/api/admin.teams.settings.setDiscoverability"
-d '{"team_id": "T0XXXXXXX", "discoverability": "invite_only"}'
curl -s -X POST -H "Authorization: Bearer ${SLACK_ADMIN_TOKEN}"
-H "Content-Type: application/json"
"https://slack.com/api/admin.teams.settings.setDiscoverability"
-d '{"team_id": "T0XXXXXXX", "discoverability": "invite_only"}'
-H "Content-Type: application/json"
"https://slack.com/api/admin.teams.settings.setDiscoverability"
-d '{"team_id": "T0XXXXXXX", "discoverability": "invite_only"}'
Force re-authentication every 24 hours
强制每24小时重新认证
curl -s -X POST -H "Authorization: Bearer ${SLACK_ADMIN_TOKEN}"
-H "Content-Type: application/json"
"https://slack.com/api/admin.teams.settings.setSessionDuration"
-d '{"team_id": "T0XXXXXXX", "session_duration": 86400}'
-H "Content-Type: application/json"
"https://slack.com/api/admin.teams.settings.setSessionDuration"
-d '{"team_id": "T0XXXXXXX", "session_duration": 86400}'
curl -s -X POST -H "Authorization: Bearer ${SLACK_ADMIN_TOKEN}"
-H "Content-Type: application/json"
"https://slack.com/api/admin.teams.settings.setSessionDuration"
-d '{"team_id": "T0XXXXXXX", "session_duration": 86400}'
-H "Content-Type: application/json"
"https://slack.com/api/admin.teams.settings.setSessionDuration"
-d '{"team_id": "T0XXXXXXX", "session_duration": 86400}'
Set message retention to 1 year
设置消息保留时长为1年
curl -s -X POST -H "Authorization: Bearer ${SLACK_ADMIN_TOKEN}"
-H "Content-Type: application/json"
"https://slack.com/api/admin.teams.settings.setRetentionPolicy"
-d '{"team_id": "T0XXXXXXX", "retention_type": "all", "retention_duration": 365}'
-H "Content-Type: application/json"
"https://slack.com/api/admin.teams.settings.setRetentionPolicy"
-d '{"team_id": "T0XXXXXXX", "retention_type": "all", "retention_duration": 365}'
curl -s -X POST -H "Authorization: Bearer ${SLACK_ADMIN_TOKEN}"
-H "Content-Type: application/json"
"https://slack.com/api/admin.teams.settings.setRetentionPolicy"
-d '{"team_id": "T0XXXXXXX", "retention_type": "all", "retention_duration": 365}'
-H "Content-Type: application/json"
"https://slack.com/api/admin.teams.settings.setRetentionPolicy"
-d '{"team_id": "T0XXXXXXX", "retention_type": "all", "retention_duration": 365}'
Audit Slack Connect shared channels
审计Slack Connect共享频道
curl -s -H "Authorization: Bearer ${SLACK_ADMIN_TOKEN}"
"https://slack.com/api/admin.conversations.search?search_channel_types=connect"
| jq '.conversations[] | {name: .name, is_ext_shared: .is_ext_shared}'
"https://slack.com/api/admin.conversations.search?search_channel_types=connect"
| jq '.conversations[] | {name: .name, is_ext_shared: .is_ext_shared}'
---curl -s -H "Authorization: Bearer ${SLACK_ADMIN_TOKEN}"
"https://slack.com/api/admin.conversations.search?search_channel_types=connect"
| jq '.conversations[] | {name: .name, is_ext_shared: .is_ext_shared}'
"https://slack.com/api/admin.conversations.search?search_channel_types=connect"
| jq '.conversations[] | {name: .name, is_ext_shared: .is_ext_shared}'
---5. Google Workspace Hardening
5. Google Workspace安全强化
bash
undefinedbash
undefinedEnforce 2-Step Verification and strong passwords
强制启用两步验证和强密码
gam update org "/" settings 2sv enforced
gam update org "/" settings password_length 14
gam update org "/" settings 2sv enforced
gam update org "/" settings password_length 14
Block all third-party OAuth apps, then whitelist specific ones
阻止所有第三方OAuth应用,然后白名单指定应用
gam update org "/" settings oauth_access block_all
gam update org "/" settings oauth_access whitelist client_id:APP_CLIENT_ID_1
gam update org "/" settings oauth_access block_all
gam update org "/" settings oauth_access whitelist client_id:APP_CLIENT_ID_1
Disable external Drive sharing and file transfers
禁用外部Drive共享和文件传输
gam update org "/" settings drive sharing_outside_domain off
gam update org "/" settings drive transfer_to_personal off
gam update org "/" settings groups external_members off
gam update org "/" settings drive sharing_outside_domain off
gam update org "/" settings drive transfer_to_personal off
gam update org "/" settings groups external_members off
Verify email authentication records
验证邮件认证记录
dig TXT company.com | grep "v=spf1"
dig TXT google._domainkey.company.com
dig TXT _dmarc.company.com
dig TXT company.com | grep "v=spf1"
dig TXT google._domainkey.company.com
dig TXT _dmarc.company.com
Expected: v=DMARC1; p=reject; rua=mailto:dmarc-reports@company.com; pct=100
预期配置:v=DMARC1; p=reject; rua=mailto:dmarc-reports@company.com; pct=100
Mobile device management
移动设备管理
gam update org "/" settings mobile management advanced
gam update org "/" settings mobile screen_lock required
gam update org "/" settings mobile encryption required
gam update mobile ${DEVICE_ID} action wipe # compromised device
---gam update org "/" settings mobile management advanced
gam update org "/" settings mobile screen_lock required
gam update org "/" settings mobile encryption required
gam update mobile ${DEVICE_ID} action wipe # 受 compromise 的设备
---6. AWS Account Security
6. AWS账户安全
bash
undefinedbash
undefinedRoot account lockdown — verify MFA, remove access keys
根账户锁定——验证MFA状态,移除访问密钥
aws iam get-account-summary --query 'SummaryMap.AccountMFAEnabled'
aws iam get-account-summary --query 'SummaryMap.AccountAccessKeysPresent'
aws iam get-account-summary --query 'SummaryMap.AccountMFAEnabled'
aws iam get-account-summary --query 'SummaryMap.AccountAccessKeysPresent'
SSO permission set with least privilege
最小权限的SSO权限集
aws sso-admin create-permission-set --instance-arn "${SSO_INSTANCE_ARN}"
--name "DeveloperAccess" --session-duration "PT8H" aws sso-admin attach-managed-policy-to-permission-set
--instance-arn "${SSO_INSTANCE_ARN}" --permission-set-arn "${PERMISSION_SET_ARN}"
--managed-policy-arn "arn:aws:iam::aws:policy/ReadOnlyAccess"
--name "DeveloperAccess" --session-duration "PT8H" aws sso-admin attach-managed-policy-to-permission-set
--instance-arn "${SSO_INSTANCE_ARN}" --permission-set-arn "${PERMISSION_SET_ARN}"
--managed-policy-arn "arn:aws:iam::aws:policy/ReadOnlyAccess"
undefinedaws sso-admin create-permission-set --instance-arn "${SSO_INSTANCE_ARN}"
--name "DeveloperAccess" --session-duration "PT8H" aws sso-admin attach-managed-policy-to-permission-set
--instance-arn "${SSO_INSTANCE_ARN}" --permission-set-arn "${PERMISSION_SET_ARN}"
--managed-policy-arn "arn:aws:iam::aws:policy/ReadOnlyAccess"
--name "DeveloperAccess" --session-duration "PT8H" aws sso-admin attach-managed-policy-to-permission-set
--instance-arn "${SSO_INSTANCE_ARN}" --permission-set-arn "${PERMISSION_SET_ARN}"
--managed-policy-arn "arn:aws:iam::aws:policy/ReadOnlyAccess"
undefinedService Control Policies
服务控制策略(SCP)
json
{
"Version": "2012-10-17",
"Statement": [
{"Sid": "DenyRootActions", "Effect": "Deny", "Action": "*", "Resource": "*",
"Condition": {"StringLike": {"aws:PrincipalArn": "arn:aws:iam::*:root"}}},
{"Sid": "DenyLeaveOrg", "Effect": "Deny",
"Action": "organizations:LeaveOrganization", "Resource": "*"}
]
}bash
aws organizations create-policy --name "DenyRootActions" \
--type SERVICE_CONTROL_POLICY --content file://deny-root-actions.json
aws organizations attach-policy --policy-id "${POLICY_ID}" --target-id "${ORG_ROOT_ID}"json
{
"Version": "2012-10-17",
"Statement": [
{"Sid": "DenyRootActions", "Effect": "Deny", "Action": "*", "Resource": "*",
"Condition": {"StringLike": {"aws:PrincipalArn": "arn:aws:iam::*:root"}}},
{"Sid": "DenyLeaveOrg", "Effect": "Deny",
"Action": "organizations:LeaveOrganization", "Resource": "*"}
]
}bash
aws organizations create-policy --name "DenyRootActions" \
--type SERVICE_CONTROL_POLICY --content file://deny-root-actions.json
aws organizations attach-policy --policy-id "${POLICY_ID}" --target-id "${ORG_ROOT_ID}"Organization-wide CloudTrail
组织级CloudTrail
aws cloudtrail create-trail --name org-security-trail
--s3-bucket-name company-cloudtrail-logs
--is-multi-region-trail --is-organization-trail --enable-log-file-validation aws cloudtrail start-logging --name org-security-trail
--s3-bucket-name company-cloudtrail-logs
--is-multi-region-trail --is-organization-trail --enable-log-file-validation aws cloudtrail start-logging --name org-security-trail
---aws cloudtrail create-trail --name org-security-trail
--s3-bucket-name company-cloudtrail-logs
--is-multi-region-trail --is-organization-trail --enable-log-file-validation aws cloudtrail start-logging --name org-security-trail
--s3-bucket-name company-cloudtrail-logs
--is-multi-region-trail --is-organization-trail --enable-log-file-validation aws cloudtrail start-logging --name org-security-trail
---7. OAuth App Review
7. OAuth应用审查
Identify High-Risk Grants
识别高风险授权
bash
undefinedbash
undefinedGoogle — find apps with dangerous scopes
Google — 查找具有危险权限范围的应用
gam all users show tokens | grep -E "(drive|gmail|admin)" > high_risk_oauth.txt
gam all users show tokens | grep -E "(drive|gmail|admin)" > high_risk_oauth.txt
GitHub — find apps with write access
GitHub — 查找具有写入权限的应用
gh api /orgs/{ORG}/installations --paginate
--jq '.installations[] | select(.permissions.contents == "write") | {app: .app_slug}'
--jq '.installations[] | select(.permissions.contents == "write") | {app: .app_slug}'
undefinedgh api /orgs/{ORG}/installations --paginate
--jq '.installations[] | select(.permissions.contents == "write") | {app: .app_slug}'
--jq '.installations[] | select(.permissions.contents == "write") | {app: .app_slug}'
undefinedRevoke Dangerous Grants
撤销危险授权
bash
gam user compromised@company.com delete token clientid APP_CLIENT_ID # single app
gam user compromised@company.com delete tokens # all apps
gh api -X DELETE /orgs/{ORG}/installations/{INSTALLATION_ID} # GitHub app
curl -s -X POST -H "Authorization: Bearer ${SLACK_ADMIN_TOKEN}" \
-H "Content-Type: application/json" \
"https://slack.com/api/admin.apps.uninstall" -d '{"app_id": "A0XXXXXXX"}'bash
gam user compromised@company.com delete token clientid APP_CLIENT_ID # 单个应用
gam user compromised@company.com delete tokens # 所有应用
gh api -X DELETE /orgs/{ORG}/installations/{INSTALLATION_ID} # GitHub应用
curl -s -X POST -H "Authorization: Bearer ${SLACK_ADMIN_TOKEN}" \
-H "Content-Type: application/json" \
"https://slack.com/api/admin.apps.uninstall" -d '{"app_id": "A0XXXXXXX"}'Scope Risk Classification
权限范围风险分级
CRITICAL — revoke unless justified:
Google: mail.google.com, admin.directory.user | GitHub: admin:org, repo | Slack: admin
HIGH — review carefully:
Google: googleapis.com/auth/drive | GitHub: contents:write | Slack: channels:read
LOW — generally safe:
Google: userinfo.email | GitHub: read:org | Slack: identity.basicCRITICAL(高危)—— 除非有正当理由否则立即撤销:
Google: mail.google.com, admin.directory.user | GitHub: admin:org, repo | Slack: admin
HIGH(中危)—— 需仔细审查:
Google: googleapis.com/auth/drive | GitHub: contents:write | Slack: channels:read
LOW(低危)—— 通常安全:
Google: userinfo.email | GitHub: read:org | Slack: identity.basic8. Admin Account Protection
8. 管理员账户保护
bash
undefinedbash
undefinedDedicated admin account in Google Workspace
在Google Workspace中创建专用管理员账户
gam create user admin-jdoe@company.com firstname "John (Admin)" lastname "Doe"
password "$(openssl rand -base64 32)" org "/Admins" gam update user admin-jdoe@company.com admin on
password "$(openssl rand -base64 32)" org "/Admins" gam update user admin-jdoe@company.com admin on
gam create user admin-jdoe@company.com firstname "John (Admin)" lastname "Doe"
password "$(openssl rand -base64 32)" org "/Admins" gam update user admin-jdoe@company.com admin on
password "$(openssl rand -base64 32)" org "/Admins" gam update user admin-jdoe@company.com admin on
Require hardware security keys for the Admins OU
要求Admins组织单元使用硬件安全密钥
gam update org "/Admins" settings 2sv security_key_only
gam update org "/Admins" settings 2sv security_key_only
AWS MFA enforcement policy
AWS MFA强制策略
cat <<'EOF' > enforce-mfa-policy.json
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "DenyUnlessMFA", "Effect": "Deny",
"NotAction": ["iam:CreateVirtualMFADevice","iam:EnableMFADevice",
"iam:GetUser","iam:ListMFADevices","sts:GetSessionToken"],
"Resource": "*",
"Condition": {"BoolIfExists": {"aws:MultiFactorAuthPresent": "false"}}
}]
}
EOF
aws iam create-policy --policy-name EnforceMFA --policy-document file://enforce-mfa-policy.json
cat <<'EOF' > enforce-mfa-policy.json
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "DenyUnlessMFA", "Effect": "Deny",
"NotAction": ["iam:CreateVirtualMFADevice","iam:EnableMFADevice",
"iam:GetUser","iam:ListMFADevices","sts:GetSessionToken"],
"Resource": "*",
"Condition": {"BoolIfExists": {"aws:MultiFactorAuthPresent": "false"}}
}]
}
EOF
aws iam create-policy --policy-name EnforceMFA --policy-document file://enforce-mfa-policy.json
Break-glass account for SSO outages
为SSO故障创建应急管理员账户
BREAK_GLASS_PW=$(openssl rand -base64 48)
gam create user breakglass@company.com firstname "Break" lastname "Glass"
password "${BREAK_GLASS_PW}" org "/Admins" admin on
password "${BREAK_GLASS_PW}" org "/Admins" admin on
BREAK_GLASS_PW=$(openssl rand -base64 48)
gam create user breakglass@company.com firstname "Break" lastname "Glass"
password "${BREAK_GLASS_PW}" org "/Admins" admin on
password "${BREAK_GLASS_PW}" org "/Admins" admin on
Store password in a sealed envelope in a physical safe
将密码存入密封信封并放置在物理保险柜中
After every use: rotate password, re-seal, log the incident
每次使用后:轮换密码、重新密封、记录事件
---
---9. Data Loss Prevention
9. 数据丢失防护(DLP)
bash
undefinedbash
undefinedGoogle Drive — block external sharing and restrict viewers
Google Drive — 阻止外部共享并限制查看者权限
gam update org "/" settings drive sharing_outside_domain off
gam update org "/" settings drive disable_download_print_copy_for_viewers on
gam update org "/" settings drive sharing_outside_domain off
gam update org "/" settings drive disable_download_print_copy_for_viewers on
GitHub — enable secret scanning and push protection org-wide
GitHub — 启用组织级密钥扫描和推送保护
gh api -X PATCH /orgs/{ORG} -f security_product=secret_scanning -f enablement=enable_all
gh api -X PATCH /orgs/{ORG} -f security_product=secret_scanning_push_protection -f enablement=enable_all
gh api /orgs/{ORG}/secret-scanning/alerts --paginate
--jq '.[] | {repo: .repository.name, secret_type: .secret_type, state: .state}'
--jq '.[] | {repo: .repository.name, secret_type: .secret_type, state: .state}'
gh api -X PATCH /orgs/{ORG} -f security_product=secret_scanning -f enablement=enable_all
gh api -X PATCH /orgs/{ORG} -f security_product=secret_scanning_push_protection -f enablement=enable_all
gh api /orgs/{ORG}/secret-scanning/alerts --paginate
--jq '.[] | {repo: .repository.name, secret_type: .secret_type, state: .state}'
--jq '.[] | {repo: .repository.name, secret_type: .secret_type, state: .state}'
Slack — restrict data export to org admins
Slack — 限制仅组织管理员可导出数据
curl -s -X POST -H "Authorization: Bearer ${SLACK_ADMIN_TOKEN}"
-H "Content-Type: application/json"
"https://slack.com/api/admin.teams.settings.setExportRestrictions"
-d '{"team_id": "T0XXXXXXX", "export_type": "org_admins_only"}'
-H "Content-Type: application/json"
"https://slack.com/api/admin.teams.settings.setExportRestrictions"
-d '{"team_id": "T0XXXXXXX", "export_type": "org_admins_only"}'
curl -s -X POST -H "Authorization: Bearer ${SLACK_ADMIN_TOKEN}"
-H "Content-Type: application/json"
"https://slack.com/api/admin.teams.settings.setExportRestrictions"
-d '{"team_id": "T0XXXXXXX", "export_type": "org_admins_only"}'
-H "Content-Type: application/json"
"https://slack.com/api/admin.teams.settings.setExportRestrictions"
-d '{"team_id": "T0XXXXXXX", "export_type": "org_admins_only"}'
AWS — block all public S3 access at account level
AWS — 在账户级别阻止所有S3公共访问
aws s3control put-public-access-block --account-id "${AWS_ACCOUNT_ID}"
--public-access-block-configuration
"BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"
--public-access-block-configuration
"BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"
---aws s3control put-public-access-block --account-id "${AWS_ACCOUNT_ID}"
--public-access-block-configuration
"BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"
--public-access-block-configuration
"BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"
---10. Shadow IT Detection
10. 影子IT检测
DNS-Based Discovery
基于DNS的发现
bash
SHADOW_IT_DOMAINS=("airtable.com" "notion.so" "trello.com" "asana.com"
"monday.com" "clickup.com" "figma.com" "canva.com" "miro.com"
"zapier.com" "dropbox.com" "box.com" "wetransfer.com")
for domain in "${SHADOW_IT_DOMAINS[@]}"; do
count=$(grep -c "${domain}" /var/log/dns/query.log 2>/dev/null || echo "0")
[ "${count}" -gt 0 ] && echo "DETECTED: ${domain} — ${count} queries"
donebash
SHADOW_IT_DOMAINS=("airtable.com" "notion.so" "trello.com" "asana.com"
"monday.com" "clickup.com" "figma.com" "canva.com" "miro.com"
"zapier.com" "dropbox.com" "box.com" "wetransfer.com")
for domain in "${SHADOW_IT_DOMAINS[@]}"; do
count=$(grep -c "${domain}" /var/log/dns/query.log 2>/dev/null || echo "0")
[ "${count}" -gt 0 ] && echo "DETECTED: ${domain} — ${count} queries"
doneGoogle Workspace Login Audit
Google Workspace登录审计
bash
gam report login parameters app_name \
start_time "2026-03-01T00:00:00Z" end_time "2026-03-24T23:59:59Z" > login_audit.csv
gam report token > token_usage_report.csvbash
gam report login parameters app_name \
start_time "2026-03-01T00:00:00Z" end_time "2026-03-24T23:59:59Z" > login_audit.csv
gam report token > token_usage_report.csvProxy Log Analysis
代理日志分析
bash
awk '{print $7}' /var/log/squid/access.log | sed 's|https\?://||;s|/.*||' \
| sort | uniq -c | sort -rn | head -50 > top_domains.txt
comm -23 <(awk '{print $2}' top_domains.txt | sort) \
<(yq '.tools[].domains[]' saas-inventory.yaml | sort) > unapproved.txtbash
awk '{print $7}' /var/log/squid/access.log | sed 's|https\?://||;s|/.*||' \
| sort | uniq -c | sort -rn | head -50 > top_domains.txt
comm -23 <(awk '{print $2}' top_domains.txt | sort) \
<(yq '.tools[].domains[]' saas-inventory.yaml | sort) > unapproved.txtAutomated Alerting
自动化告警
bash
cat <<'SCRIPT' > /usr/local/bin/shadow-it-check.sh
#!/usr/bin/env bash
set -euo pipefail
APPROVED="/etc/security/approved-saas-domains.txt"
YESTERDAY=$(date -d "yesterday" +%d-%b-%Y)
grep "${YESTERDAY}" /var/log/dns/query.log | awk '{print $4}' | sort -u > /tmp/today.txt
NEW=$(comm -23 /tmp/today.txt <(sort "${APPROVED}"))
[ -n "${NEW}" ] && mail -s "[ALERT] Shadow IT" security@company.com <<< "${NEW}"
SCRIPT
chmod +x /usr/local/bin/shadow-it-check.sh
echo "0 8 * * * root /usr/local/bin/shadow-it-check.sh" >> /etc/cron.d/shadow-it-checkbash
cat <<'SCRIPT' > /usr/local/bin/shadow-it-check.sh
#!/usr/bin/env bash
set -euo pipefail
APPROVED="/etc/security/approved-saas-domains.txt"
YESTERDAY=$(date -d "yesterday" +%d-%b-%Y)
grep "${YESTERDAY}" /var/log/dns/query.log | awk '{print $4}' | sort -u > /tmp/today.txt
NEW=$(comm -23 /tmp/today.txt <(sort "${APPROVED}"))
[ -n "${NEW}" ] && mail -s "[ALERT] Shadow IT" security@company.com <<< "${NEW}"
SCRIPT
chmod +x /usr/local/bin/shadow-it-check.sh
echo "0 8 * * * root /usr/local/bin/shadow-it-check.sh" >> /etc/cron.d/shadow-it-checkQuick Reference — Top 10 Priority Actions
快速参考——十大优先行动
| # | Action | Scope |
|---|---|---|
| 1 | Enforce MFA/2FA everywhere | Google, GitHub, AWS, Slack |
| 2 | Enable SSO with your IdP | All tools |
| 3 | Audit and revoke OAuth grants | Google, GitHub |
| 4 | Require Slack app approval | Slack |
| 5 | Branch protection on main | GitHub |
| 6 | Secret scanning + push protection | GitHub |
| 7 | Block public S3 buckets | AWS |
| 8 | Enable org-wide CloudTrail | AWS |
| 9 | Disable external Drive sharing | |
| 10 | Create break-glass admin accounts | Google, AWS |
| # | 行动 | 适用范围 |
|---|---|---|
| 1 | 全面强制启用MFA/2FA | Google、GitHub、AWS、Slack |
| 2 | 通过身份提供商启用SSO | 所有工具 |
| 3 | 审计并撤销OAuth授权 | Google、GitHub |
| 4 | 启用Slack应用审批要求 | Slack |
| 5 | 配置主分支保护 | GitHub |
| 6 | 启用密钥扫描+推送保护 | GitHub |
| 7 | 阻止S3公共存储桶 | AWS |
| 8 | 启用组织级CloudTrail | AWS |
| 9 | 禁用Drive外部共享 | |
| 10 | 创建应急管理员账户 | Google、AWS |
Maintenance Cadence
维护周期
Weekly: Review OAuth grants, secret scanning alerts, Slack app queue.
Monthly: AWS IAM report, rotate service keys, admin account review, shadow IT scan.
Quarterly: Full SaaS inventory refresh, OAuth pruning, break-glass test, SCP updates.
每周: 审查OAuth授权、密钥扫描告警、Slack应用审批队列。
每月: AWS IAM报告、轮换服务密钥、管理员账户审查、影子IT扫描。
每季度: 全面更新SaaS资产清单、清理OAuth授权、测试应急账户、更新SCP策略。