This commit is contained in:
dicolanl 2020-06-10 02:01:38 +00:00
Родитель d5f76f6d84
Коммит 8ed46e4919
24 изменённых файлов: 1512 добавлений и 163 удалений

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,7 +1,7 @@
# Ingest GitHub AuditLog and API Data
Author: Nicholas DiCola
Get-GitHubAuditEntry playbook ingests GitHub AuditLog via (GraphQL)[https://developer.github.com/v4/interface/auditentry/] events and writes them to a custom log table called GitHub_CL. Get-GitHubTrafficLogs playbook ingests GitHub (Traffic Logs)[https://developer.github.com/v3/repos/traffic/] data and writes them to a custom log table called GitHubTraffic_CL.
Get-GitHubAuditEntry playbook ingests GitHub AuditLog via (GraphQL)[https://developer.github.com/v4/interface/auditentry/] events and writes them to a custom log table called GitHub_CL. Get-GitHubRepoLogs playbook ingests GitHub (Traffic Logs)[https://developer.github.com/v3/repos/traffic/] data and writes them to a custom log table called GitHubRepoLogs_CL. Get-GitHubVulnerabilityAlerts playbook ingests GitHub (Security Vulnerability)[https://developer.github.com/v4/object/securityvulnerability/] data and writes them to a custom log table called GitHubRepoLogs_CL
There are a number of configuration steps required to deploy the Logic App playbooks.
@ -17,14 +17,16 @@ This user will be used to grant access to the Key Vault secret.
"workspaceId": The Sentinel Workspace ID
"workSpaceKey": The Sentinel Workspace Key
```
4. There are two json files (ORGS.json and lastrun.json).
4. There are two json files (ORGS.json and lastrun-Audit.json).
5. Edit the ORGS.json file and update "org": "sampleorg" and replace sample org with your org name. If you have addtional orgs, add another line {"org": "sampleorg"} for each org.
6. Upload the ORGS.json and lastrun.json to the storage account githublogicapp container.
6. Upload the ORGS.json, and lastrun-Audit.json to the storage account githublogicapp container.
7. Go to the keyvault-GitHubPlaybooks connection resource.
8. Click Edit API Connection.
9. Click Authorize. Sign in as the user. Click Save.
10. The playbooks are deployed as disabled since the json files and connection has to be authorized. Go to each playbook and click Enable.
Note: there are two parsers (here)[https://github.com/Azure/Azure-Sentinel/tree/master/Parsers/GitHub] to make the logs useful
## Deploy the Logic App template
<a href="https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FAzure-Sentinel%2Fmaster%2FDataConnectors%2FGitHub%2Fazuredeploy.json" target="_blank">
<img src="https://aka.ms/deploytoazurebutton""/>

Просмотреть файл

@ -22,15 +22,15 @@ query: |
let StartTime = 1h;
let EndRunTime = StartTime - RunTime;
let EndLearningTime = StartTime + LearningPeriod;
let GitHubCountryCodeLogs = (GitHub_CL
| extend TimeGenerated = node_createdAt_t
| where node_actorLocation_countryCode_s != "");
let GitHubCountryCodeLogs = (GitHubAudit
| where Country != "");
GitHubCountryCodeLogs
| where TimeGenerated between (ago(EndLearningTime) .. ago(StartTime))
| summarize makeset(node_actorLocation_countryCode_s) by node_actorLogin_s
| summarize makeset(Country) by Actor
| join kind=innerunique (
GitHubCountryCodeLogs
| where TimeGenerated between (ago(StartTime) .. ago(EndRunTime))
| distinct node_actorLocation_countryCode_s, node_actorLogin_s
) on node_actorLogin_s
| where set_node_actorLocation_countryCode_s !contains node_actorLocation_countryCode_s
| distinct Country, Actor
) on Actor
| where set_Country !contains Country
| extend AccountCustomEntity = Actor, IPCustomEntity = IPAddress

Просмотреть файл

@ -39,4 +39,5 @@ query: |
| summarize FailedLoginsCountInRunTime = count() by User = Identity
) on User
| where FailedLoginsCountInRunTime > LearningThreshold
| extend AccountCustomEntity = UserPrincipalName, IPCustomEntity = IPAddress

Просмотреть файл

@ -1,7 +1,7 @@
id:
name: (Preview) TI map Domain entity to CommonSecurityLog
id: aac495a9-feb1-446d-b08e-a1164a539452
name: TI map IP entity to GitHub_CL
description: |
'Identifies a match in CommonSecurityLog table from any Domain IOC from TI'
'Identifies a match in GitHub_CL table from any IP IOC from TI'
severity: Medium
requiredDataConnectors:
- connectorId: ThreatIntelligence
@ -15,7 +15,7 @@ queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
- ????
- Impact
query: |
ThreatIntelligenceIndicator
@ -28,12 +28,11 @@ query: |
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
| join (
GitHub_CL
// renaming time column so it is clear the log this came from
| extend GitHubActivity_TimeGenerated = TimeGenerated
| extend TimeGenerated = node_createdAt_t
GitHubAudit
| where TimeGenerated >= ago(24h)
| extned GitHubAudit_TimeGenerated = TimeGenerated
)
on on $left.TI_ipEntity == $right.node_actorIp_s
on on $left.TI_ipEntity == $right.IPaddress
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| project LatestIndicatorTime, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, GitHubActivity_TimeGenerated, TI_ipEntity, actorIp_s, actorLogin_s, action_s, actorLocation_country_s, operationType_s, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress
| project LatestIndicatorTime, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, GitHubAudit_TimeGenerated, TI_ipEntity, IPaddress, Actor, Action, Country, OperationType, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress
| extend timestamp = GitHubAudit_TimeGenerated, IPCustomEntity = IPaddress, AccountCustomEntity = Actor

Просмотреть файл

@ -24,5 +24,6 @@ query: |
| where ResultType == 0
| summarize CountOfLocations = dcount(Location), Locations = make_set(Location) by User = Identity
| where CountOfLocations > 1
| extend AccountCustomEntity = UserPrincipalName, IPCustomEntity = IPAddress

Просмотреть файл

@ -18,8 +18,8 @@ relevantTechniques:
query: |
let timeframe = 14d;
GitHub_CL
| extend TimeGenerated = node_createdAt_t
GitHubAudit
| where TimeGenerated > ago(timeframe)
| where action_s == "org.disable_two_factor_requirement"
| project ["Action"]=node_action_s , ["TimeGenerated"]=TimeGenerated ,["User"]=node_actorLogin_s ,["Location"]=node_actorLocation_country_s
| where Action == "org.disable_two_factor_requirement"
| project TimeGenerated, Action, Actor, Country, IPaddress, Repository
| extend AccountCustomEntity = Actor, IPCustomEntity = IPaddress

Просмотреть файл

@ -17,15 +17,14 @@ query: |
let StartTime = 1h;
let EndRunTime = StartTime - RunTime;
let EndLearningTime = StartTime + LearningPeriod;
let GitHubOrgMemberLogs = (GitHub_CL
| extend TimeGenerated = node_createdAt_t
| where node_action_s == "org.invite_member" or node_action_s == "org.update_member" or node_action_s == "org.add_member");
let GitHubOrgMemberLogs = (GitHubAudit
where Action == "org.invite_member" or Action == "org.update_member" or Action == "org.add_member");
GitHubOrgMemberLogs
| where TimeGenerated between (ago(EndLearningTime) .. ago(StartTime))
| distinct node_actorLogin_s
| distinct Actor
| join kind=rightanti (
GitHubOrgMemberLogs
| where TimeGenerated between (ago(StartTime) .. ago(EndRunTime))
| distinct node_actorLogin_s
) on node_actorLogin_s
| distinct Actor
) on Actor

Просмотреть файл

@ -17,14 +17,13 @@ query: |
let StartTime = 1h;
let EndRunTime = StartTime - RunTime;
let EndLearningTime = StartTime + LearningPeriod;
let GitHubRepositoryDestroyEvents = (GitHub_CL
| extend TimeGenerated = node_createdAt_t
| where node_action_s == "repo.destroy");
let GitHubRepositoryDestroyEvents = (GitHubAudit
| where Action == "repo.destroy");
GitHubRepositoryDestroyEvents
| where TimeGenerated between (ago(EndLearningTime) .. ago(StartTime))
| distinct node_actorLogin_s
| distinct Actor
| join kind=rightanti (
GitHubRepositoryDestroyEvents
| where TimeGenerated between (ago(StartTime) .. ago(EndRunTime))
| distinct node_actorLogin_s
) on node_actorLogin_s
| distinct Actor
) on Actor

Просмотреть файл

@ -17,35 +17,33 @@ query: |
let StartTime = 1h;
let EndRunTime = StartTime - RunTime;
let EndLearningTime = StartTime + LearningPeriod;
let GitHubActorLogin = (GitHub_CL
| extend TimeGenerated = node_createdAt_t
| where node_actorLogin_s != "");
let GitHubUser = (GitHub_CL
| extend TimeGenerated = node_createdAt_t
| where node_userLogin_s != "");
let GitHubActorLogin = (GitHubAudit
| where Actor != "");
let GitHubUser = (GitHubAudit
| where ImpactedUser != "");
let GitHubNewActorLogin = (GitHubActorLogin
| where TimeGenerated between (ago(EndLearningTime) .. ago(StartTime))
| summarize makeset(node_actorLogin_s)
| summarize makeset(Actor)
| extend Dummy = 1
| join kind=innerunique (
GitHubActorLogin
| where TimeGenerated between (ago(StartTime) .. ago(EndRunTime))
| distinct node_actorLogin_s
| distinct Actor
| extend Dummy = 1
) on Dummy
| project-away Dummy
| where set_node_actorLogin_s !contains node_actorLogin_s);
| where set_Actor !contains Actor);
let GitHubNewUser = ( GitHubUser
| where TimeGenerated between (ago(EndLearningTime) .. ago(StartTime))
| summarize makeset(userLogin_s)
| summarize makeset(ImpactedUser)
| extend Dummy = 1
| join kind=innerunique (
GitHubUser
| where TimeGenerated between (ago(StartTime) .. ago(EndRunTime))
| distinct node_userLogin_s
| distinct ImpactedUser
| extend Dummy = 1
) on Dummy
| project-away Dummy
| where set_node_userLogin_s !contains node_userLogin_s);
| where set_ImpactedUser !contains ImpactedUser);
union GitHubNewActorLogin, GitHubNewUser

Просмотреть файл

@ -20,9 +20,8 @@ query: |
let MinThreshold = 10.0;
let EndRunTime = StartTime - RunTime;
let EndLearningTime = StartTime + LearningPeriod;
let GitHubRepositoryDestroyEvents = (GitHub_CL
| extend TimeGenerated = node_createdAt_t
| where action_s == "repo.destroy");
let GitHubRepositoryDestroyEvents = (GitHubAudit
| where Action == "repo.destroy");
GitHubRepositoryDestroyEvents
| where TimeGenerated between (ago(EndLearningTime) .. ago(StartTime))
| summarize count() by bin(TimeGenerated, BinTime)

Просмотреть файл

@ -13,8 +13,7 @@ relevantTechniques:
query: |
let timeframe = 14d;
GitHub_CL
| extend TimeGenerated = node_createdAt_t
GitHubAudit
| where TimeGenerated > ago(timeframe)
| where node_action_s == "org.disable_oauth_app_restrictions"
| project ["Action"]=node_action_s , ["TimeGenerated"]=TimeGenerated ,["User"]=node_actorLogin_s ,["Location"]=node_actorLocation_country_s
| where Action == "org.disable_oauth_app_restrictions"
| project TimeGenerated, Action, Actor, Location

Просмотреть файл

@ -5,7 +5,7 @@ description: |
requiredDataConnectors:
- connectorId: CustomConnector
dataTypes:
- GithubTrafficLogs_CL
- GithubRepoLogs_CL
tactics:
- Collection
relevantTechniques:
@ -17,7 +17,7 @@ query: |
let max_t = toscalar(GithubTrafficLogs_CL
| summarize max(timestamp_t));
GithubTrafficLogs_CL
| where LogType_s == "clones"
| make-series num=count(count_d) default=0 on timestamp_t in range(min_t, max_t, 1h) by Repository_s
| where Action == "clones"
| make-series num=count(count_d) default=0 on timestamp_t in range(min_t, max_t, 1h) by Repository
| extend (anomalies, score, baseline) = series_decompose_anomalies(num, 1.5, -1, 'linefit')
| render timechart

Просмотреть файл

@ -13,10 +13,9 @@ relevantTechniques:
query: |
let timeframe = 14d;
GitHub_CL
| extend TimeGenerated = node_createdAt_t
GitHubAudit
| where TimeGenerated > ago(timeframe)
| where node_action_s == "repo.access"
| where node_operationType_s == "MODIFY"
| where Action == "repo.access"
| where OperationType == "MODIFY"
| where node_visibility_s == "PUBLIC"
| project ["Action"]=node_action_s , ["TimeGenerated"]=TimeGenerated, ["User"]=node_actorLogin_s ,["Location"]=node_actorLocation_country_s, ["Repo Name"]=node_repositoryName_s, ["Permission"]=node_visibility_s
| project TimeGenerated, Action, Actor, Country, Repository, Visability

Просмотреть файл

@ -12,7 +12,6 @@ relevantTechniques:
- T1098
query: |
GitHub_CL
| extend TimeGenerated = node_createdAt_t
| where node_action_s == "org.update_default_repository_permission"
| project ["Action"]=node_action_s, ["TimeGenerated"]=TimeGenerated, ["User"]=node_actorLogin_s, ["Location"]=node_actorLocation_country_s, ["Repo Name"]=node_repositoryName_s, ["Previous Permission"]=node_permissionWas_s, ["New Permission"]=node_permission_s
GitHubAudit
| where Action == "org.update_default_repository_permission"
| project TimeGenerated, Action, Actor, Country, Repository, PreviousPermission, CurrentPermission

Просмотреть файл

@ -12,18 +12,16 @@ relevantTechniques:
- T1098
query: |
GitHub_CL
| extend TimeGenerated = node_createdAt_t
| where node_userLogin_s != ""
| where node_action_s == "org.invite_member" or node_action_s == "org.add_member" or node_action_s == "team.add_member" or node_action_s == "repo.add_member"
| distinct node_userLogin_s, TimeGenerated, node_actorLogin_s
| project-rename firstUserAdded = node_userLogin_s, firstEventTime = TimeGenerated, firstAdderUser = node_actorLogin_s
GitHubAudit
| where ImpactedUser != ""
| where Action == "org.invite_member" or Action == "org.add_member" or Action == "team.add_member" or Action == "repo.add_member"
| distinct ImpactedUser, TimeGenerated, Actor
| project-rename firstUserAdded = ImpactedUser, firstEventTime = TimeGenerated, firstAdderUser = Actor
| join kind= innerunique (
GitHub_CL
| extend TimeGenerated = node_createdAt_t
| where node_userLogin_s != ""
| where node_action_s == "org.invite_member" or node_action_s == "org.add_member" or node_action_s == "team.add_member" or node_action_s == "repo.add_member"
| distinct node_userLogin_s, TimeGenerated, node_actorLogin_s
| project-rename secondUserAdded = node_userLogin_s, secondEventTime = TimeGenerated, secondAdderUser = node_actorLogin_s
GitHubAudit
| where ImpactedUser != ""
| where Action == "org.invite_member" or Action == "org.add_member" or Action == "team.add_member" or Action == "repo.add_member"
| distinct ImpactedUser, TimeGenerated, Actor
| project-rename secondUserAdded = ImpactedUser, secondEventTime = TimeGenerated, secondAdderUser = Actor
) on $right.secondAdderUser == $left.firstUserAdded
| where secondEventTime between (firstEventTime .. (firstEventTime + 1h))

Просмотреть файл

@ -0,0 +1,48 @@
// GitHub Enterprise Audit Entry Data Parser
// Last Updated Date: Jun 7, 2020
//
//This parser parses GitHub Enterprise Audit Entry extract the infromation from their various components. It is assumed that the playbook to ingest audit entry data into Sentinel is enabled
//
// Parser Notes:
// 1. This parser assumes logs are collected into a custom log table entitled GitHub_CL
//
// Usage Instruction :
// Paste below query in log analytics, click on Save button and select as Function from drop down by specifying function name and alias.
// To work with pre-built GitHub queries this Function should be given the alias of GitHubAudit.
// Functions usually takes 10-15 minutes to activate. You can then use function alias from any other queries (e.g. GitHubAudit | take 10).
//
// References :
// Using functions in Azure monitor log queries : https://docs.microsoft.com/azure/azure-monitor/log-query/functions
// Tech Community Blog on KQL Functions : https://techcommunity.microsoft.com/t5/Azure-Sentinel/Using-KQL-functions-to-speed-up-analysis-in-Azure-Sentinel/ba-p/712381
// Tech Community Blog on GitHub data: <>
//
//
GitHub_CL
| project TimeGenerated=node_createdAt_t,
Organization=columnifexists('node_organizationName_s', ""),
Action=node_action_s,
OperationType=node_operationType_s,
Repository=columnifexists('node_repositoryName_s',""),
Actor=node_actorLogin_s,
IPaddress=node_actorIp_s,
City=node_actorLocation_city_s,
Country=node_actorLocation_country_s,
ImpactedUser=columnifexists('node_userLogin_s', ""),
ImpactedUserEmail=columnifexists('node_user_email_s', ""),
InvitedUserPermission=node_permission_s,
Visability=columnifexists('node_visibility_s',""),
OauthApplication=columnifexists('node_oauthApplicationName_s',""),
OauthApplicationUrl=columnifexists('node_applicationUrl_s',""),
OauthApplicationState=columnifexists('node_state_s',""),
UserCanInviteCollaborators=columnifexists('node_canInviteOutsideCollaboratorsToRepositories_b',""),
MembershipType=columnifexists('node_membershipTypes_s',""),
CurrentPermission=columnifexists('node_permission_s',""),
PreviousPermission=columnifexists('node_permissionWas_s',""),
TeamName=columnifexists('node_teamName_s',""),
Reason=columnifexists('node_reason_s',""),
BlockedUser=columnifexists('node_blockedUserName_s',""),
CanCreateRepositories=columnifexists('canCreateRepositories_b',"")

Просмотреть файл

@ -0,0 +1,45 @@
// GitHub Enterprise Repository Data Parser
// Last Updated Date: Jun 7, 2020
//
//This parser parses GitHub Enterprise Repository Data extract the infromation from their various components. It is assumed that the playbook to ingest repository data into Sentinel is enabled
//
// Parser Notes:
// 1. This parser assumes logs are collected into a custom log table entitled GitHubRepoLogs_CL
//
// Usage Instruction :
// Paste below query in log analytics, click on Save button and select as Function from drop down by specifying function name and alias.
// To work with pre-built GitHub queries this Function should be given the alias of GitHubRepo
// Functions usually takes 10-15 minutes to activate. You can then use function alias from any other queries (e.g. GitHubRepo | take 10).
//
// References :
// Using functions in Azure monitor log queries : https://docs.microsoft.com/azure/azure-monitor/log-query/functions
// Tech Community Blog on KQL Functions : https://techcommunity.microsoft.com/t5/Azure-Sentinel/Using-KQL-functions-to-speed-up-analysis-in-Azure-Sentinel/ba-p/712381
// Tech Community Blog on GitHub data: <>
//
//
GitHubRepoLogs_CL
| project TimeGenerated = created_at_t,
Organization=columnifexists('Organization_s', ""),
Repository=columnifexists('Repository_s',""),
Action=columnifexists('LogType_s',""),
Actor=coalesce(login_s, owner_login_s),
ActorType=coalesce(owner_type_s, type_s),
IsPrivate=columnifexists('private_b',""),
ForksUrl=columnifexists('forks_url_s',""),
PushedAt=columnifexists('pushed_at_t',""),
IsDisabled=columnifexists('disabled_b',""),
AdminPermissions=columnifexists('permissions_admin_b',""),
PushPermissions=columnifexists('permissions_push_b',""),
PullPermissions=columnifexists('permissions_pull_b',""),
ForkCount=columnifexists('forks_count_d',""),
Count=columnifexists('count_d,',""),
UniqueUsersCount=columnifexists('uniques_d',""),
DismmisedAt=columnifexists('dismissedAt_t',""),
Reason=columnifexists('dismissReason_s',""),
vulnerableManifestFilename = columnifexists('vulnerableManifestFilename_s',""),
Description=columnifexists('securityAdvisory_description_s',""),
Link=columnifexists('securityAdvisory_permalink_s',""),
PublishedAt=columnifexists('securityAdvisory_publishedAt_t ',""),
Severity=columnifexists('securityAdvisory_severity_s',""),
Summary=columnifexists('securityAdvisory_summary_s',"")

Просмотреть файл

@ -0,0 +1,189 @@
{
"version": "Notebook/1.0",
"items": [
{
"type": 1,
"content": {
"json": "## GitHub - Security\n"
},
"name": "text - 2"
},
{
"type": 9,
"content": {
"version": "KqlParameterItem/1.0",
"parameters": [
{
"id": "a9923eb9-9a02-4a48-bb72-e9be338eeb3b",
"version": "KqlParameterItem/1.0",
"name": "TimeRange",
"type": 4,
"value": {
"durationMs": 1209600000
},
"typeSettings": {
"selectableValues": [
{
"durationMs": 300000
},
{
"durationMs": 900000
},
{
"durationMs": 1800000
},
{
"durationMs": 3600000
},
{
"durationMs": 14400000
},
{
"durationMs": 43200000
},
{
"durationMs": 86400000
},
{
"durationMs": 172800000
},
{
"durationMs": 259200000
},
{
"durationMs": 604800000
},
{
"durationMs": 1209600000
},
{
"durationMs": 2419200000
},
{
"durationMs": 2592000000
},
{
"durationMs": 5184000000
},
{
"durationMs": 7776000000
}
]
},
"resourceType": "microsoft.insights/components"
}
],
"style": "pills",
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces"
},
"name": "parameters - 2"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
"query": "GitHub_CL\n| extend TimeGenerated = node_createdAt_t\n| where node_action_s == \"org.add_member\" or node_action_s == \"org.remove_member\"\n| extend MemberName = node_userLogin_s\n| extend Action = iif(node_action_s==\"org.add_member\", \"Added\", \"Removed\")\n| extend Organization = node_organizationName_s\n| extend Permission = node_permission_s\n| sort by TimeGenerated desc\n| project MemberName, Action, Organization, Permission\n",
"size": 1,
"title": "Members Added or Removed",
"timeContext": {
"durationMs": 0
},
"timeContextFromParameter": "TimeRange",
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces"
},
"customWidth": "50",
"name": "membersaddedorremoved"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
"query": "GitHub_CL\r\n| extend TimeGenerated = node_createdAt_t\r\n| where node_action_s == \"repo.create\"\r\n| extend RepoName = node_repositoryName_s\r\n| extend Actor = node_actorLogin_s\r\n| extend Private = node_visibility_s\r\n| sort by TimeGenerated desc\r\n| project RepoName, Actor, Private\r\n",
"size": 0,
"title": "Repositories Created",
"timeContext": {
"durationMs": 0
},
"timeContextFromParameter": "TimeRange",
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces"
},
"customWidth": "50",
"name": "repositoriescreated"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
"query": "GitHub_CL\r\n| extend TimeGenerated = node_createdAt_t\r\n| where node_action_s == \"team.add_repository\" or node_action_s == \"team.remove_repository\"\r\n| extend Organization = node_organizationName_s\r\n| extend RepoName = node_repositoryName_s\r\n| extend TeamName = node_teamName_s\r\n| extend Action = iif(node_action_s==\"team.add_repository\", \"Added\", \"Removed\")\r\n| sort by TimeGenerated desc\r\n| project Organization, RepoName, TeamName, Action\r\n",
"size": 0,
"title": "Teams Added/Removed Repository",
"timeContext": {
"durationMs": 0
},
"timeContextFromParameter": "TimeRange",
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces"
},
"customWidth": "50",
"name": "teamsaddedremovedtorepository"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
"query": "GitHub_CL\r\n| extend TimeGenerated = node_createdAt_t\r\n| where node_action_s == \"repo.access\" and node_operationType_s == \"MODIFY\" and node_visibility_s == \"PUBLIC\"\r\n| extend Organiation = node_organizationName_s\r\n| extend Repo = node_repositoryName_s\r\n| extend Actor = node_actorLogin_s\r\n| sort by TimeGenerated desc\r\n| project Organiation, Repo, Actor\r\n",
"size": 0,
"title": "Private Repos made Public",
"timeContext": {
"durationMs": 0
},
"timeContextFromParameter": "TimeRange",
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces"
},
"customWidth": "50",
"name": "privatereposmadepublic"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
"query": "GitHubRepoLogs_CL\r\n| extend TimeGenerated = created_at_t\r\n| where LogType_s == \"Forks\"\r\n| summarize count() by bin(TimeGenerated, 1d), name_s",
"size": 0,
"title": "Fork Count by Repoistory over Time",
"timeContext": {
"durationMs": 0
},
"timeContextFromParameter": "TimeRange",
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"visualization": "barchart"
},
"customWidth": "50",
"name": "query - 6"
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
"query": "GitHubRepoLogs_CL\r\n| where LogType_s == \"Clones\"\r\n| extend TimeGenerated = timestamp_t\r\n| summarize count() by bin(TimeGenerated, 1d), Repository_s",
"size": 0,
"title": "Clone count by Repository Over Time",
"timeContext": {
"durationMs": 0
},
"timeContextFromParameter": "TimeRange",
"queryType": 0,
"resourceType": "microsoft.operationalinsights/workspaces",
"visualization": "barchart"
},
"customWidth": "50",
"name": "query - 7"
}
],
"fromTemplateId": "sentinel-GitHubSecurity",
"$schema": "https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json"
}

Просмотреть файл

@ -0,0 +1,34 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="1600.000000pt" height="1600.000000pt" viewBox="0 0 1600.000000 1600.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,1600.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M7125 14990 c-1163 -71 -2251 -432 -3211 -1066 -1581 -1044 -2631
-2735 -2863 -4609 -38 -303 -46 -444 -45 -815 0 -393 12 -581 60 -910 292
-2044 1535 -3814 3373 -4805 260 -140 593 -287 876 -387 133 -47 145 -49 226
-46 116 4 210 49 298 143 67 72 132 194 150 283 7 34 11 220 11 513 0 434 -1
460 -17 455 -10 -3 -88 -17 -173 -32 -130 -22 -196 -27 -410 -31 -275 -5 -412
7 -615 58 -407 100 -786 348 -1025 670 -80 107 -102 147 -167 292 -203 455
-382 704 -648 902 -245 181 -286 284 -140 345 54 22 74 24 190 24 108 -1 147
-5 228 -27 322 -86 589 -290 802 -612 291 -440 689 -654 1285 -690 187 -11
449 22 616 78 l69 23 7 154 c14 301 52 511 117 655 21 46 27 67 18 70 -7 2
-82 18 -167 35 -1039 208 -1867 666 -2375 1315 -411 525 -614 1184 -592 1920
25 831 290 1525 795 2083 l76 83 -17 27 c-200 311 -265 899 -151 1362 45 182
133 383 220 501 35 48 37 49 87 49 162 0 432 -41 624 -95 418 -118 847 -370
1158 -681 l95 -95 69 25 c225 81 556 149 931 192 195 22 823 31 1043 14 423
-31 845 -105 1102 -193 l70 -24 115 111 c330 319 766 561 1210 670 173 42 311
63 480 72 l125 7 47 -70 c138 -209 224 -462 259 -763 17 -151 7 -472 -20 -625
-28 -158 -64 -281 -112 -384 l-39 -83 61 -67 c81 -88 221 -274 290 -386 249
-403 391 -830 456 -1375 24 -207 24 -684 -1 -865 -50 -368 -127 -628 -276
-930 -147 -300 -286 -492 -534 -740 -273 -272 -527 -455 -881 -632 -399 -201
-866 -354 -1355 -444 -36 -7 -66 -13 -68 -15 -2 -1 12 -35 31 -76 40 -82 60
-152 84 -295 15 -86 17 -242 22 -1288 6 -1125 7 -1193 25 -1240 36 -99 81
-171 151 -241 95 -96 160 -126 280 -132 83 -3 98 -1 195 33 1491 522 2753
1583 3528 2967 826 1473 1039 3233 591 4874 -350 1283 -1109 2451 -2144 3299
-1030 844 -2266 1343 -3605 1455 -170 14 -723 20 -895 10z"/>
</g>
</svg>

После

Ширина:  |  Высота:  |  Размер: 2.1 KiB

Двоичные данные
Workbooks/Images/Preview/GitHubSecurityBlack.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 168 KiB

Двоичные данные
Workbooks/Images/Preview/GitHubSecurityWhite.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 181 KiB

Просмотреть файл

@ -674,5 +674,18 @@
"templateRelativePath": "Perimeter81OverviewWorkbook.json",
"subtitle": "",
"provider": "Perimeter 81"
},
{
"workbookKey": "GitHubSecurityWorkbook",
"logoFileName": "github-logo.svg",
"description": "Gain insights to GitHub activities that may be interesting for security.",
"dataTypesDependencies": [ "Github_CL", "GitHubRepoLogs_CL" ],
"dataConnectorsDependencies": [ ],
"previewImagesFileNames": [ "GitHubSecurityWhite.png", "GitHubSecurityBlack.png"],
"version": "1.0",
"title": "GitHub Security",
"templateRelativePath": "GitHubSecurityWorkbook.json",
"subtitle": "",
"provider": "Azure Sentinel community"
}
]