forked from canada-ca/tracker
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrequest-discovery.js
More file actions
137 lines (122 loc) · 4.4 KB
/
Copy pathrequest-discovery.js
File metadata and controls
137 lines (122 loc) · 4.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import { t } from '@lingui/macro'
import { GraphQLID, GraphQLNonNull, GraphQLString } from 'graphql'
import { fromGlobalId, mutationWithClientMutationId } from 'graphql-relay'
import { Domain } from '../../scalars'
import { logActivity } from '../../audit-logs'
export const requestDiscovery = new mutationWithClientMutationId({
name: 'RequestDiscovery',
description: 'This mutation is used to start a subdomain discovery scan on a requested domain.',
inputFields: () => ({
domain: {
type: Domain,
description: 'The base domain that the subdomain scan will be ran on.',
},
orgId: {
type: new GraphQLNonNull(GraphQLID),
description: 'The global id of the organization you wish to assign new found domains to.',
},
}),
outputFields: () => ({
status: {
type: GraphQLString,
description: 'Informs the user if the scan was dispatched successfully.',
resolve: ({ status }) => status,
},
}),
mutateAndGetPayload: async (
args,
{
query,
collections,
transaction,
i18n,
userKey,
publish,
request: { ip },
auth: { checkDomainPermission, userRequired, verifiedRequired, checkSuperAdmin, superAdminRequired },
loaders: { loadDomainByDomain, loadOrgByKey },
validators: { cleanseInput },
},
) => {
// Get User
const user = await userRequired()
verifiedRequired({ user })
// Keep feature to super admins while in beta
const isSuperAdmin = await checkSuperAdmin()
superAdminRequired({ user, isSuperAdmin })
// Cleanse input
const { type: _orgType, id: orgId } = fromGlobalId(cleanseInput(args.orgId))
const domainInput = cleanseInput(args.domain)
// Check to see if domain is valid for subdomain discovery.
// Discovery should not be performed on a domain that is not a subdomain of canada.ca or gc.ca, or on the root domains themselves
const regex = /^[A-Za-z0-9](?:[A-Za-z0-9\-.]+[A-Za-z0-9])?.(canada|gc).ca$/gm
const found = domainInput.match(regex)
if (typeof found === 'undefined' || found?.length !== 1) {
console.warn(
`User: ${userKey} attempted to start a subdomain discovery scan on: ${domainInput} however domain is not a valid domain.`,
)
throw new Error(i18n._(t`Unable to request a subdomain discovery scan on an invalid domain.`))
}
// Check to see if domain exists
const domain = await loadDomainByDomain.load(domainInput)
if (typeof domain === 'undefined') {
console.warn(
`User: ${userKey} attempted to start a subdomain discovery scan on: ${domainInput} however domain cannot be found.`,
)
throw new Error(i18n._(t`Unable to request a subdomain discovery scan on an unknown domain.`))
}
// Check to see if org exists
const org = await loadOrgByKey.load(orgId)
if (typeof org === 'undefined') {
console.warn(
`User: ${userKey} attempted to discover subdomains in an organization: ${orgId} that does not exist.`,
)
return {
_type: 'error',
code: 400,
description: i18n._(t`Unable to discover domains for unknown organization.`),
}
}
// Check to see if user has access to domain
const permission = await checkDomainPermission({ domainId: domain._id })
if (!permission) {
console.warn(
`User: ${userKey} attempted to start a subdomain discovery scan on: ${domain.domain} however they do not have permission to do so.`,
)
throw new Error(
i18n._(t`Permission Denied: Please contact organization user for help with scanning this domain.`),
)
}
await publish({
channel: `scans.discovery`,
msg: {
domain: domain.domain,
orgId: org._id,
},
})
await logActivity({
transaction,
collections,
query,
initiatedBy: {
id: user._key,
userName: user.userName,
role: permission,
ipAddress: ip,
},
action: 'discover',
target: {
resource: domain.domain,
organization: {
id: org._id,
name: org.name,
}, // name of resource being acted upon
resourceType: 'domain', // user, org, domain
},
})
console.info(`User: ${userKey} successfully dispatched a subdomain discovery scan on domain: ${domain.domain}.`)
return {
status: i18n._(t`Successfully dispatched subdomain discovery scan.`),
}
},
})