Skip to main content

saas-security-posture

Audit and harden your SaaS tool stack — enforce SSO, review OAuth grants, manage shadow IT, and secure admin accounts across Slack, GitHub, Google Workspace, and AWS. Use when tightening security across company SaaS tools.

Datos de origen

Repositorio
BagelHole/DevOps-Security-Agent-Skills
Última actividad en el origen
24 de marzo de 2026 a las 22:02
Idioma detectado de SKILL.md
inglés
Estrellas
1162
Forks
165

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
saas-security-posture
description
Audit and harden your SaaS tool stack — enforce SSO, review OAuth grants, manage shadow IT, and secure admin accounts across Slack, GitHub, Google Workspace, and AWS. Use when tightening security across company SaaS tools.
license
MIT
metadata
{"author":"devops-skills","version":"1.0"}
# SaaS Security Posture Management for Startups Secure every SaaS tool your company relies on with practical, command-driven hardening. ## 1. When to Use This Skill - **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. ## 2. SaaS Inventory Audit ### Google Workspace — OAuth Grants ```bash gam all users show tokens > oauth_tokens_audit.csv ``` ### GitHub — Installed Apps ```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 ```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 ```bash aws iam generate-credential-report aws iam get-credential-report --output text --query 'Content' | base64 -d > iam_credential_report.csv ``` ### Master 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: true ``` --- ## 3. GitHub Security Hardening ```bash # Enforce 2FA and find non-compliant members 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 gh api /orgs/{ORG}/credential-authorizations --paginate \ --jq '.[] | {login: .login, saml_name_id: .saml_name_id}' # Add IP allow list entry 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 # 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 # Audit PATs and revoke stale tokens 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} # Audit deploy keys and webhooks 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 ```bash # Require 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}' # 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"}' # Force re-authentication every 24 hours 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}' # Set message retention to 1 year 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}' # Audit Slack Connect shared channels 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}' ``` --- ## 5. Google Workspace Hardening ```bash # Enforce 2-Step Verification and strong passwords gam update org "/" settings 2sv enforced gam update org "/" settings password_length 14 # Block all third-party OAuth apps, then whitelist specific ones 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 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 # Expected: 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 ``` --- ## 6. AWS Account Security ```bash # Root account lockdown — verify MFA, remove access keys aws iam get-account-summary --query 'SummaryMap.AccountMFAEnabled' aws iam get-account-summary --query 'SummaryMap.AccountAccessKeysPresent' # SSO permission set with least privilege 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" ``` ### Service Control Policies ```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 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 ``` --- ## 7. OAuth App Review ### Identify High-Risk Grants ```bash # Google — find apps with dangerous scopes gam all users show tokens | grep -E "(drive|gmail|admin)" > high_risk_oauth.txt # GitHub — find apps with write access gh api /orgs/{ORG}/installations --paginate \ --jq '.installations[] | select(.permissions.contents == "write") | {app: .app_slug}' ``` ### Revoke 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"}' ``` ### 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.basic ``` --- ## 8. Admin Account Protection ```bash # Dedicated admin account in 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 # Require hardware security keys for the Admins OU gam update org "/Admins" settings 2sv security_key_only # AWS MFA enforcement policy 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 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 # Store password in a sealed envelope in a physical safe # After every use: rotate password, re-seal, log the incident ``` --- ## 9. Data Loss Prevention ```bash # Google Drive — block external sharing and restrict viewers 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 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}' # Slack — restrict data export to org admins 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"}' # AWS — block all public S3 access at account level aws s3control put-public-access-block --account-id "${AWS_ACCOUNT_ID}" \
Ver en GitHub
Este SKILL.md es muy grande, por eso SkillsMP muestra aqui solo la primera seccion. Ver en GitHub