Detection rules › Panther

Panther rules: asana

Asana Service Account Created

#
Severity
medium
Log types
Asana.Audit
Reference
help.asana.com
Source
github.com/panther-labs/panther-analysis

An Asana service account was created by someone in your organization.

Detection logic

def rule(event):
    return event.get("event_type", "<NO_EVENT_TYPE_FOUND>") == "service_account_created"


def title(event):
    actor_email = event.deep_get("actor", "email", default="<ACTOR_NOT_FOUND>")
    svc_acct_name = event.deep_get("resource", "name", default="<SVC_ACCT_NAME_NOT_FOUND>")
    return f"Asana user [{actor_email}] created a new service account [{svc_acct_name}]."

Rule specification

AnalysisType: rule
Description: An Asana service account was created by someone in your organization.
DisplayName: "Asana Service Account Created"
Enabled: true
Filename: asana_service_account_created.py
Runbook: Confirm this user acted with valid business intent and determine whether this activity was authorized.
Reference: https://help.asana.com/hc/en-us/articles/14217496838427-Service-Accounts
Severity: Medium
DedupPeriodMinutes: 60
LogTypes:
  - Asana.Audit
RuleID: "Asana.Service.Account.Created"
Threshold: 1

Stages and Predicates

Fires on Asana.Audit events when the condition below holds.

Condition

  • event_type is service_account_created

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event_typeeq
  • service_account_created
field:"event_type" kind:eq value:"service_account_created"

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
emailactor.email
nameresource.name

Response runbook

Confirm this user acted with valid business intent and determine whether this activity was authorized.

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "actor_type": "user",
    "email": "homer.simpson@panther.io",
    "gid": "12345",
    "name": "Homer Simpson"
  },
  "context": {
    "client_ip_address": "12.12.12.12",
    "context_type": "web",
    "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
  },
  "created_at": "2022-12-16 19:28:18.396",
  "details": {},
  "event_category": "apps",
  "event_type": "service_account_created",
  "gid": "12345",
  "resource": {
    "gid": "12345",
    "name": "Slack Service Account",
    "resource_type": "user"
  }
}

Asana Team Privacy Public

#
Severity
low
Log types
Asana.Audit
Reference
help.asana.com
Source
github.com/panther-labs/panther-analysis

An Asana team's privacy setting was changed to public to the organization (not public to internet)

Detection logic

def rule(event):
    return (
        event.get("event_type") == "team_privacy_settings_changed"
        and event.deep_get("details", "new_value") == "public"
    )


def title(event):
    team = event.deep_get("resource", "name", default="<TEAM_NOT_FOUND>")
    actor = event.deep_get("actor", "email", default="<ACTOR_NOT_FOUND>")
    return f"Asana team [{team}] has been made public to the org by [{actor}]."

Rule specification

AnalysisType: rule
Description: An Asana team's privacy setting was changed to public to the organization (not public to internet)
DisplayName: "Asana Team Privacy Public"
Enabled: true
Filename: asana_team_privacy_public.py
Reference: https://help.asana.com/hc/en-us/articles/14211433439387-Team-permissions
Severity: Low
DedupPeriodMinutes: 60
LogTypes:
  - Asana.Audit
RuleID: "Asana.Team.Privacy.Public"
Threshold: 1

Stages and Predicates

Fires on Asana.Audit events when all of the conditions below hold.

Condition

  • event_type is team_privacy_settings_changed
  • details.new_value is public

Indicators

These rows show field, operator, and value matches.

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
nameresource.name
emailactor.email

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "actor_type": "user",
    "email": "homer.simpson@panther.io",
    "gid": "12345",
    "name": "Homer Simpson"
  },
  "context": {
    "client_ip_address": "12.12.12.12",
    "context_type": "web",
    "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
  },
  "created_at": "2022-12-16 19:35:21.026",
  "details": {
    "new_value": "public"
  },
  "event_category": "access_control",
  "event_type": "team_privacy_settings_changed",
  "gid": "12345",
  "p_log_type": "Asana.Audit",
  "resource": {
    "gid": "12345",
    "name": "Example Team Name",
    "resource_type": "team"
  }
}

Asana Workspace Default Session Duration Never

#
Severity
low
Log types
Asana.Audit
Reference
help.asana.com
Source
github.com/panther-labs/panther-analysis

An Asana workspace's default session duration (how often users need to re-authenticate) has been changed to never.

Detection logic

def rule(event):
    return (
        event.get("event_type") == "workspace_default_session_duration_changed"
        and event.deep_get("details", "new_value") == "never"
    )


def title(event):
    workspace = event.deep_get("resource", "name", default="<WORKSPACE_NOT_FOUND>")
    actor = event.deep_get("actor", "email", default="<ACTOR_NOT_FOUND>")
    return (
        f"Asana workspace [{workspace}]'s default session duration "
        f"has been set to never expire by [{actor}]."
    )

Rule specification

AnalysisType: rule
Description: "An Asana workspace's default session duration (how often users need to re-authenticate) has been changed to never. "
DisplayName: "Asana Workspace Default Session Duration Never"
Enabled: true
Filename: asana_workspace_default_session_duration_never.py
Reference: https://help.asana.com/hc/en-us/articles/14218320495899-Manage-Session-Duration
Severity: Low
DedupPeriodMinutes: 60
LogTypes:
  - Asana.Audit
RuleID: "Asana.Workspace.Default.Session.Duration.Never"
Threshold: 1

Stages and Predicates

Fires on Asana.Audit events when all of the conditions below hold.

Condition

  • event_type is workspace_default_session_duration_changed
  • details.new_value is never

Indicators

These rows show field, operator, and value matches.

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
nameresource.name
emailactor.email

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "actor_type": "user",
    "email": "homer@example.io",
    "gid": "12345",
    "name": "Homer Simpson"
  },
  "context": {
    "client_ip_address": "12.12.12.12",
    "context_type": "web",
    "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
  },
  "created_at": "2022-12-16 19:31:13.887",
  "details": {
    "new_value": "never",
    "old_value": "14 days"
  },
  "event_category": "admin_settings",
  "event_type": "workspace_default_session_duration_changed",
  "gid": "12345",
  "resource": {
    "gid": "12345",
    "name": "Acme Co",
    "resource_type": "workspace"
  }
}

Asana Workspace Email Domain Added

#
Severity
low
Log types
Asana.Audit
Reference
help.asana.com
Source
github.com/panther-labs/panther-analysis

A new email domain has been added to an Asana workspace. Reviewer should validate that the new domain is a part of the organization.

Detection logic

def rule(event):
    return event.get("event_type") == "workspace_associated_email_domain_added"


def title(event):
    workspace = event.deep_get("resource", "name", default="<WORKSPACE_NOT_FOUND>")
    domain = event.deep_get("details", "new_value", default="<DOMAIN_NOT_FOUND>")
    actor = event.deep_get("actor", "email", default="<ACTOR_NOT_FOUND>")
    return f"Asana new email domain [{domain}] added to Workspace [{workspace}] by [{actor}]."

Rule specification

AnalysisType: rule
Description: "A new email domain has been added to an Asana workspace. Reviewer should validate that the new domain is a part of the organization. "
DisplayName: "Asana Workspace Email Domain Added"
Enabled: true
Filename: asana_workspace_email_domain_added.py
Reference: https://help.asana.com/hc/en-us/articles/15901227439515-Email-domain-management-for-Asana-organizations
Severity: Low
DedupPeriodMinutes: 60
LogTypes:
  - Asana.Audit
RuleID: "Asana.Workspace.Email.Domain.Added"
Threshold: 1

Stages and Predicates

Fires on Asana.Audit events when the condition below holds.

Condition

  • event_type is workspace_associated_email_domain_added

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event_typeeq
  • workspace_associated_email_domain_added
field:"event_type" kind:eq value:"workspace_associated_email_domain_added"

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
new_valuedetails.new_value
nameresource.name
emailactor.email

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "actor_type": "user",
    "email": "homer.simpson@example.io",
    "gid": "12345",
    "name": "Homer Simpson"
  },
  "context": {
    "client_ip_address": "12.12.12.12",
    "context_type": "web",
    "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
  },
  "created_at": "2022-12-16 19:30:26.15",
  "details": {
    "new_value": "test.com"
  },
  "event_category": "admin_settings",
  "event_type": "workspace_associated_email_domain_added",
  "gid": "12345",
  "resource": {
    "gid": "12345",
    "name": "Example IO",
    "resource_type": "workspace"
  }
}

Asana Workspace Form Link Auth Requirement Disabled

#
Severity
low
Log types
Asana.Audit
Reference
help.asana.com
Source
github.com/panther-labs/panther-analysis

An Asana Workspace Form Link is a unique URL that allows you to create a task directly within a specific Workspace or Project in Asana, using a web form. Disabling authentication requirements may allow unauthorized users to create tasks.

Detection logic

def rule(event):
    return event.get("event_type") == "workspace_form_link_authentication_required_disabled"


def title(event):
    workspace = event.deep_get("resource", "name", default="<WORKSPACE_NOT_FOUND>")
    actor = event.deep_get("actor", "email", default="<ACTOR_NOT_FOUND>")
    return (
        f"Asana Workspace [{workspace}] Form Link Auth Requirement " f" was disabled by [{actor}]."
    )

Rule specification

AnalysisType: rule
Description: "An Asana Workspace Form Link is a unique URL that allows you to create a task directly within a specific Workspace or Project in Asana, using a web form. Disabling authentication requirements may allow unauthorized users to create tasks. "
DisplayName: "Asana Workspace Form Link Auth Requirement Disabled"
Enabled: true
Filename: asana_workspace_form_link_auth_requirement_disabled.py
Reference: https://help.asana.com/hc/en-us/articles/14111697664923-Forms-access-permissions#:~:text=SSO%2C%20SAML%2C%20or-,no%20authentication%20method,-).%20If%20no%20authentication
Severity: Low
DedupPeriodMinutes: 60
LogTypes:
  - Asana.Audit
RuleID: "Asana.Workspace.Form.Link.Auth.Requirement.Disabled"
Threshold: 1

Stages and Predicates

Fires on Asana.Audit events when the condition below holds.

Condition

  • event_type is workspace_form_link_authentication_required_disabled

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event_typeeq
  • workspace_form_link_authentication_required_disabled
field:"event_type" kind:eq value:"workspace_form_link_authentication_required_disabled"

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
nameresource.name
emailactor.email

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "actor_type": "user",
    "email": "homer.simpson@simpsons.com",
    "gid": "1234567890",
    "name": "Homer Simpson"
  },
  "context": {
    "client_ip_address": "1.2.3.4",
    "context_type": "web",
    "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
  },
  "created_at": "2022-12-16 19:32:00.922",
  "details": {},
  "event_category": "admin_settings",
  "event_type": "workspace_form_link_authentication_required_disabled",
  "gid": "1234567890",
  "resource": {
    "gid": "111234",
    "name": "Simpsons Lab",
    "resource_type": "workspace"
  }
}

Asana Workspace Guest Invite Permissions Anyone

#
Severity
low
Log types
Asana.Audit
Reference
help.asana.com
Source
github.com/panther-labs/panther-analysis

Typically inviting guests to Asana is permitted by few users. Enabling anyone to invite guests can potentially lead to unauthorized users gaining access to Asana.

Detection logic

def rule(event):
    return (
        event.get("event_type") == "workspace_guest_invite_permissions_changed"
        and event.deep_get("details", "new_value") == "anyone"
    )


def title(event):
    workspace = event.deep_get("resource", "name", default="<WORKSPACE_NOT_FOUND>")
    actor = event.deep_get("actor", "email", default="<ACTOR_NOT_FOUND>")
    return (
        f"Asana Workspace [{workspace}] guest invite permissions "
        f"changed to anyone by [{actor}]."
    )

Rule specification

AnalysisType: rule
Description: Typically inviting guests to Asana is permitted by few users. Enabling anyone to invite guests can potentially lead to unauthorized users gaining access to Asana.
DisplayName: "Asana Workspace Guest Invite Permissions Anyone"
Enabled: true
Filename: asana_workspace_guest_invite_permissions_anyone.py
Reference: https://help.asana.com/hc/en-us/articles/14109494654875-Admin-console#:~:text=Google%20SSO%20password.-,Guest%20invite%20controls,-Super%20admins%20of
Severity: Low
DedupPeriodMinutes: 60
LogTypes:
  - Asana.Audit
RuleID: "Asana.Workspace.Guest.Invite.Permissions.Anyone"
Threshold: 1

Stages and Predicates

Fires on Asana.Audit events when all of the conditions below hold.

Condition

  • event_type is workspace_guest_invite_permissions_changed
  • details.new_value is anyone

Indicators

These rows show field, operator, and value matches.

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
nameresource.name
emailactor.email

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "actor_type": "user",
    "email": "homer.simpson@example.io",
    "gid": "12345",
    "name": "Homer Simpson"
  },
  "context": {
    "client_ip_address": "12.12.12.12",
    "context_type": "web",
    "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
  },
  "created_at": "2022-12-16 19:30:26.15",
  "details": {
    "new_value": "anyone",
    "old_value": "admins_only"
  },
  "event_category": "admin_settings",
  "event_type": "workspace_guest_invite_permissions_changed",
  "gid": "12345",
  "resource": {
    "gid": "12345",
    "name": "Example IO",
    "resource_type": "workspace"
  }
}

Asana Workspace New Admin

#
Severity
high
Log types
Asana.Audit
Reference
help.asana.com
Source
github.com/panther-labs/panther-analysis

Admin role was granted to the user who previously did not have admin permissions

Detection logic

from panther_asana_helpers import asana_alert_context


def rule(event):
    new = event.deep_get("details", "new_value", default="")
    old = event.deep_get("details", "old_value", default="")
    return all(
        [
            event.get("event_type") == "user_workspace_admin_role_changed",
            "admin" in new,
            "admin" not in old,
        ]
    )


def title(event):
    a_c = asana_alert_context(event)
    w_s = event.deep_get("details", "group", "name", default="<WS_NAME_NOT_FOUND>")
    return (
        f"Asana user [{a_c.get('resource_name')}] was made an admin "
        f"in workspace [{w_s}] by [{a_c.get('actor')}]."
    )


def alert_context(event):
    return asana_alert_context(event)

Rule specification

AnalysisType: rule
Description: Admin role was granted to the user who previously did not have admin permissions
DisplayName: Asana Workspace New Admin
Enabled: true
Filename: asana_workspace_new_admin.py
Reference: https://help.asana.com/hc/en-us/articles/14141552580635-Admin-and-super-admin-roles-in-Asana
Severity: High
DedupPeriodMinutes: 60
LogTypes:
  - Asana.Audit
RuleID: "Asana.Workspace.New.Admin"
Threshold: 1

Stages and Predicates

Fires on Asana.Audit events when all of the conditions below hold.

Condition

  • event_type is user_workspace_admin_role_changed
  • details.new_value contains admin
  • details.old_value does not contain admin

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
details.old_valuecontainsadminexcludes:details.old_value field:"details.old_value" value:"admin"

Indicators

These rows show field, operator, and value matches.

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
namedetails.group.name

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "actor_type": "user",
    "email": "homer.simpson@example.io",
    "gid": "1234",
    "name": "Homer Simpson"
  },
  "context": {
    "client_ip_address": "12.12.12.12",
    "context_type": "web",
    "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
  },
  "created_at": "2022-12-16 19:32:22.377",
  "details": {
    "group": {
      "gid": "1234",
      "name": "Workspace Name",
      "resource_type": "workspace"
    },
    "new_value": "domain_admin",
    "old_value": "member"
  },
  "event_category": "roles",
  "event_type": "user_workspace_admin_role_changed",
  "gid": "1234",
  "p_log_type": "Asana.Audit",
  "resource": {
    "email": "target@example.io",
    "gid": "1234",
    "name": "Bart Simpson",
    "resource_type": "user"
  }
}

Asana Workspace Org Export

#
Severity
medium
Log types
Asana.Audit
Reference
help.asana.com
Source
github.com/panther-labs/panther-analysis

An Asana user started an org export.

Detection logic

def rule(event):
    return event.get("event_type", "<NO_EVENT_TYPE_FOUND>") == "workspace_export_started"


def title(event):
    actor_email = event.deep_get("actor", "email", default="<ACTOR_NOT_FOUND>")
    context_type = event.deep_get("context", "context_type", default="<CONTEXT_TYPE_NOT_FOUND>")
    return f"Asana user [{actor_email}] started a [{context_type}] export for your organization."

Rule specification

AnalysisType: rule
Description: An Asana user started an org export.
DisplayName: Asana Workspace Org Export
Enabled: true
Filename: asana_workspace_org_export.py
Runbook: Confirm this user acted with valid business intent and determine whether this activity was authorized.
Reference: https://help.asana.com/hc/en-us/articles/14139896860955-Privacy-and-security#:~:text=like%20to%20see.-,Full%20export%20of%20an%20organization,-Available%20on%20Asana
Severity: Medium
DedupPeriodMinutes: 60
LogTypes:
  - Asana.Audit
RuleID: "Asana.Workspace.Org.Export"
Threshold: 1

Stages and Predicates

Fires on Asana.Audit events when the condition below holds.

Condition

  • event_type is workspace_export_started

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event_typeeq
  • workspace_export_started
field:"event_type" kind:eq value:"workspace_export_started"

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
emailactor.email
context_typecontext.context_type

Response runbook

Confirm this user acted with valid business intent and determine whether this activity was authorized.

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "actor_type": "user",
    "email": "homer@example.io",
    "gid": "12345",
    "name": "Homer Simpson"
  },
  "context": {
    "client_ip_address": "12.12.12.12",
    "context_type": "web",
    "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
  },
  "created_at": "2022-12-16 19:26:08.434",
  "details": {},
  "event_category": "content_export",
  "event_type": "workspace_export_started",
  "gid": "12345",
  "resource": {
    "gid": "12345",
    "name": "Example IO",
    "resource_type": "workspace"
  }
}

Asana Workspace Password Requirements Simple

#
Severity
medium
Log types
Asana.Audit
Reference
help.asana.com
Source
github.com/panther-labs/panther-analysis

An asana user made your organization's password requirements less strict.

Detection logic

def rule(event):
    new_val = event.deep_get("details", "new_value", default="<NEW_VAL_NOT_FOUND>")
    return all(
        [
            event.get("event_type", "<NO_EVENT_TYPE_FOUND>")
            == "workspace_password_requirements_changed",
            new_val == "simple",
        ]
    )


def title(event):
    actor_email = event.deep_get("actor", "email", default="<ACTOR_NOT_FOUND>")
    new_value = event.deep_get("details", "new_value", default="<NEW_VAL_NOT_FOUND>")
    old_value = event.deep_get("details", "old_value", default="<OLD_VAL_NOT_FOUND>")
    return (
        f"Asana user [{actor_email}] changed your organization's password requirements "
        f"from [{old_value}] to [{new_value}]."
    )

Rule specification

AnalysisType: rule
Description: An asana user made your organization's password requirements less strict.
DisplayName: "Asana Workspace Password Requirements Simple"
Enabled: true
Filename: asana_workspace_password_requirements_simple.py
Runbook: Confirm this user acted with valid business intent and determine whether this activity was authorized.
Reference: https://help.asana.com/hc/en-us/articles/14075208738587-Authentication-and-access-management-options-for-paid-plans
Severity: Medium
DedupPeriodMinutes: 60
LogTypes:
  - Asana.Audit
RuleID: "Asana.Workspace.Password.Requirements.Simple"
Threshold: 1

Stages and Predicates

Fires on Asana.Audit events when all of the conditions below hold.

Condition

  • event_type is workspace_password_requirements_changed
  • details.new_value is simple

Indicators

These rows show field, operator, and value matches.

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
emailactor.email
old_valuedetails.old_value
new_valuedetails.new_value

Response runbook

Confirm this user acted with valid business intent and determine whether this activity was authorized.

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "actor_type": "user",
    "email": "homer.simpson@example.io",
    "gid": "12345",
    "name": "Homer Simpson"
  },
  "context": {
    "client_ip_address": "12.12.12.12",
    "context_type": "web",
    "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
  },
  "created_at": "2022-12-16 19:31:03.667",
  "details": {
    "new_value": "simple",
    "old_value": "strong"
  },
  "event_category": "admin_settings",
  "event_type": "workspace_password_requirements_changed",
  "gid": "12345",
  "resource": {
    "gid": "12345",
    "name": "Company Example IO",
    "resource_type": "workspace"
  }
}

Asana Workspace Require App Approvals Disabled

#
Severity
medium
Log types
Asana.Audit
Reference
help.asana.com
Source
github.com/panther-labs/panther-analysis

An Asana user turned off app approval requirements for an application type for your organization.

Detection logic

def rule(event):
    new_val = event.deep_get("details", "new_value", default="<NEW_VAL_NOT_FOUND>")
    return all(
        [
            event.get("event_type", "<NO_EVENT_TYPE_FOUND>")
            == "workspace_require_app_approvals_of_type_changed",
            new_val == "off",
        ]
    )


def title(event):
    actor_email = event.deep_get("actor", "email", default="<ACTOR_NOT_FOUND>")
    context = event.deep_get("context", "context_type", default="<APP_CONTEXT_NOT_FOUND>")
    return (
        f"Asana user [{actor_email}] disabled application approval requirements "
        f"for [{context}] type applications."
    )

Rule specification

AnalysisType: rule
Description: An Asana user turned off app approval requirements for an application type for your organization.
DisplayName: Asana Workspace Require App Approvals Disabled
Enabled: true
Filename: asana_workspace_require_app_approvals_disabled.py
Runbook: Confirm this user acted with valid business intent and determine whether this activity was authorized.
Reference: https://help.asana.com/hc/en-us/articles/14109494654875-Admin-console#:~:text=used%20by%20default-,Require%20app%20approval,-Admins%20manage%20a
Severity: Medium
DedupPeriodMinutes: 60
LogTypes:
  - Asana.Audit
RuleID: "Asana.Workspace.Require.App.Approvals.Disabled"
Threshold: 1

Stages and Predicates

Fires on Asana.Audit events when all of the conditions below hold.

Condition

  • event_type is workspace_require_app_approvals_of_type_changed
  • details.new_value is off

Indicators

These rows show field, operator, and value matches.

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
emailactor.email
context_typecontext.context_type

Response runbook

Confirm this user acted with valid business intent and determine whether this activity was authorized.

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "actor_type": "user",
    "email": "homer.simpson@example.io",
    "gid": "1234",
    "name": "Homer Simpson"
  },
  "context": {
    "client_ip_address": "12.12.12.12",
    "context_type": "web",
    "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
  },
  "created_at": "2022-12-16 19:29:34.968",
  "details": {
    "new_value": "off",
    "old_value": "all_apps"
  },
  "event_category": "admin_settings",
  "event_type": "workspace_require_app_approvals_of_type_changed",
  "gid": "1234",
  "resource": {
    "gid": "1234",
    "name": "Panther Labs",
    "resource_type": "workspace"
  }
}

Asana Workspace SAML Optional

#
Severity
medium
Log types
Asana.Audit
Reference
help.asana.com
Source
github.com/panther-labs/panther-analysis

An Asana user made SAML optional for your organization.

Detection logic

def rule(event):
    old_val = event.deep_get("details", "old_value", default="<OLD_VAL_NOT_FOUND>")
    new_val = event.deep_get("details", "new_value", default="<NEW_VAL_NOT_FOUND>")
    return all(
        [
            event.get("event_type", "<NO_EVENT_TYPE_FOUND>") == "workspace_saml_settings_changed",
            old_val == "required",
            new_val == "optional",
        ]
    )


def title(event):
    actor_email = event.deep_get("actor", "email", default="<ACTOR_NOT_FOUND>")
    return f"Asana user [{actor_email}] made SAML optional for your organization."

Rule specification

AnalysisType: rule
Description: An Asana user made SAML optional for your organization.
DisplayName: "Asana Workspace SAML Optional"
Enabled: true
Filename: asana_workspace_saml_optional.py
Runbook: Confirm this user acted with valid business intent and determine whether this activity was authorized.
Reference: https://help.asana.com/hc/en-us/articles/14075208738587-Premium-Business-and-Enterprise-authentication#gl-saml:~:text=to%20your%20organization.-,SAML,-If%20your%20company
Severity: Medium
DedupPeriodMinutes: 60
LogTypes:
  - Asana.Audit
RuleID: "Asana.Workspace.SAML.Optional"
Threshold: 1

Stages and Predicates

Fires on Asana.Audit events when all of the conditions below hold.

Condition

  • event_type is workspace_saml_settings_changed
  • details.old_value is required
  • details.new_value is optional

Indicators

These rows show field, operator, and value matches.

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
emailactor.email

Response runbook

Confirm this user acted with valid business intent and determine whether this activity was authorized.

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "actor_type": "user",
    "email": "homer.simpson@example.io",
    "gid": "1234",
    "name": "Homer Simpson"
  },
  "context": {
    "client_ip_address": "12.12.12.12",
    "context_type": "web",
    "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
  },
  "created_at": "2022-12-16 19:31:36.289",
  "details": {
    "new_value": "optional",
    "old_value": "required"
  },
  "event_category": "admin_settings",
  "event_type": "workspace_saml_settings_changed",
  "gid": "1234",
  "resource": {
    "gid": "1234",
    "name": "example.io",
    "resource_type": "email_domain"
  }
}