Skip to content

Commit

Permalink
Merge pull request #22 from cloudgraphdev/feature/CG-1210
Browse files Browse the repository at this point in the history
fet(services): Create Azure logProfiles service
  • Loading branch information
tyler-dunkel authored Jun 2, 2022
2 parents e65a931 + c049a36 commit e593788
Show file tree
Hide file tree
Showing 15 changed files with 258 additions and 1 deletion.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ CloudGraph needs read permissions in order to ingest your data. To keep things e
| loadBalancer | loadBalancer, publicIp, resourceGroup, virtualNetwork |
| logAnalyticsSolution | resourceGroup, logAnalyticsWorkspace |
| logAnalyticsWorkspace | resourceGroup, dataCollectionRule, logAnalyticsSolution |
| logProfiles | storageAccount |
| networkInterface | publicIp, resourceGroup, securityGroup, virtualMachine, virtualNetwork |
| policyAssignment | |
| postgreSqlServers | resourceGroup, databasePostgreSql |
Expand All @@ -106,7 +107,7 @@ CloudGraph needs read permissions in order to ingest your data. To keep things e
| securitySettings | |
| serviceBus | resourceGroup |
| sqlServers | databaseSql, resourceGroup |
| storageAccount | diagnosticSetting, resourceGroup, storageContainer |
| storageAccount | diagnosticSetting, logProfiles, resourceGroup, storageContainer |
| storageBlob | resourceGroup, storageContainer |
| storageContainer | resourceGroup, storageAccount |
| synapseBigDataPools | resourceGroup, synapseWorkspaces |
Expand Down
1 change: 1 addition & 0 deletions src/enums/schemasMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export default {
[services.loadBalancer]: 'azureLoadBalancer',
[services.logAnalyticsSolution]: 'azureLogAnalyticsSolution',
[services.logAnalyticsWorkspace]: 'azureLogAnalyticsWorkspace',
[services.logProfiles]: 'azureLogProfiles',
[services.machineLearningWorkspaces]: 'azureMachineLearningWorkspace',
[services.metricAlert]:'azureMetricAlert',
[services.mySqlServers]: 'azureMySqlServer',
Expand Down
2 changes: 2 additions & 0 deletions src/enums/serviceMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ import AzureServiceBus from '../services/serviceBus'
import AzureBackupVault from '../services/backupVault'
import AzureBackupInstance from '../services/backupInstance'
import AzureBackupPolicy from '../services/backupPolicy'
import AzureLogProfiles from '../services/logProfiles'

/**
* serviceMap is an object that contains all currently supported services for AWS
Expand Down Expand Up @@ -142,6 +143,7 @@ export default {
[services.loadBalancer]: AzureLoadBalancer,
[services.logAnalyticsSolution]: AzureLogAnalyticsSolutions,
[services.logAnalyticsWorkspace]: AzureLogAnalyticsWorkspaces,
[services.logProfiles]: AzureLogProfiles,
[services.machineLearningWorkspaces]: AzureMachineLearningWorkspace,
[services.mySqlServers]: AzureMySqlServer,
[services.networkInterface]: AzureNetworkInterface,
Expand Down
1 change: 1 addition & 0 deletions src/enums/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export default {
loadBalancer: 'loadBalancer',
logAnalyticsSolution: 'logAnalyticsSolution',
logAnalyticsWorkspace: 'logAnalyticsWorkspace',
logProfiles: 'logProfiles',
machineLearningWorkspaces: 'machineLearningWorkspaces',
metricAlert: 'metricAlert',
mySqlServers: 'mySqlServers',
Expand Down
2 changes: 2 additions & 0 deletions src/properties/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ export default {
`Found ${num} Key Vault secrets`,
// Load balancer
foundLoadBalancers: (num: number): string => `Found ${num} load balancers`,
// Metric Profiles
foundLogProfiles: (num: number): string => `Found ${num} log profiles`,
// Machine Learning Workspaces
foundMachineLearningWorkspaces: (num: number): string => `Found ${num} machine learning workspaces`,
// Metric Alert
Expand Down
52 changes: 52 additions & 0 deletions src/services/logProfiles/connections.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { ServiceConnection } from '@cloudgraph/sdk'
import { isEmpty } from 'lodash'

import services from '../../enums/services'
import { RawAzureStorageAccount } from '../storageAccount/data'
import { RawAzureLogProfileResource } from './data'

export default ({
service,
data,
region,
}: {
service: RawAzureLogProfileResource
data: Array<{ name: string; data: { [property: string]: any[] } }>
region: string
}): {
[property: string]: ServiceConnection[]
} => {
const connections: ServiceConnection[] = []
const { id, storageAccountId } = service

/**
* Find storage account related to this log profile
*/
const storageAccounts: {
name: string
data: { [property: string]: RawAzureStorageAccount[] }
} = data.find(({ name }) => name === services.storageAccount)

if (storageAccounts?.data?.[region]) {
const storageAccountsInRegion: RawAzureStorageAccount[] =
storageAccounts.data[region].filter(
({ id: saId }: RawAzureStorageAccount) => saId === storageAccountId
)

if (!isEmpty(storageAccountsInRegion)) {
for (const rg of storageAccountsInRegion) {
connections.push({
id: rg.id,
resourceType: services.storageAccount,
relation: 'child',
field: 'storageAccount',
})
}
}
}

const rgResult = {
[id]: connections,
}
return rgResult
}
65 changes: 65 additions & 0 deletions src/services/logProfiles/data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import CloudGraph from '@cloudgraph/sdk'
import { MonitorClient, LogProfileResource } from '@azure/arm-monitor'
import { PagedAsyncIterableIterator } from '@azure/core-paging'
import azureLoggerText from '../../properties/logger'
import { AzureServiceInput, TagMap } from '../../types'
import { tryCatchWrapper } from '../../utils'
import { regionMap } from '../../enums/regions'

const { logger } = CloudGraph
const lt = { ...azureLoggerText }
const serviceName = 'Log Profiles'

export interface RawAzureLogProfileResource
extends Omit<LogProfileResource, 'location' | 'tags'> {
region: string
Tags: TagMap
}

export default async ({
config,
}: AzureServiceInput): Promise<{
[property: string]: RawAzureLogProfileResource[]
}> => {
try {
const { tokenCredentials, subscriptionId } = config
const client = new MonitorClient(tokenCredentials, subscriptionId)
const logProfiles: RawAzureLogProfileResource[] = []
const result = { global: [] }
await tryCatchWrapper(
async () => {
const logProfilesIterable: PagedAsyncIterableIterator<LogProfileResource> =
client.logProfiles.list()
for await (const logProfile of logProfilesIterable) {
if (logProfile) {
const { tags, ...rest } = logProfile
const region = regionMap.global
logProfiles.push({
...rest,
region,
Tags: tags || {},
})
}
}
},
{
service: serviceName,
client,
scope: 'logProfiles',
operation: 'list',
}
)
logger.debug(lt.foundLogProfiles(logProfiles.length))

logProfiles.map(({ region, ...rest }) => {
result.global.push({
...rest,
region,
})
})
return result
} catch (e) {
logger.error(e)
return {}
}
}
40 changes: 40 additions & 0 deletions src/services/logProfiles/format.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import cuid from 'cuid'
import { AzureLogProfile } from '../../types/generated'
import { formatTagsFromMap } from '../../utils/format'
import { RawAzureLogProfileResource } from './data'

export default ({
service,
account,
region,
}: {
service: RawAzureLogProfileResource
account: string
region: string
}): AzureLogProfile => {
const {
id,
name,
type,
storageAccountId,
serviceBusRuleId,
locations = [],
categories = [],
retentionPolicy = {},
Tags: tags = {},
} = service

return {
id: id || cuid(),
name,
region,
subscriptionId: account,
type,
storageAccountId,
serviceBusRuleId,
locations,
categories,
retentionPolicy,
tags: formatTagsFromMap(tags),
}
}
16 changes: 16 additions & 0 deletions src/services/logProfiles/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Service } from '@cloudgraph/sdk'
import BaseService from '../base'
import getConnections from './connections'
import format from './format'
import mutation from './mutation'
import getData from './data'

export default class LogProfiles extends BaseService implements Service {
format = format.bind(this)

getConnections = getConnections.bind(this)

getData = getData.bind(this)

mutation = mutation
}
5 changes: 5 additions & 0 deletions src/services/logProfiles/mutation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default `mutation($input: [AddazureLogProfileInput!]!) {
addazureLogProfile(input: $input, upsert: true) {
numUids
}
}`;
26 changes: 26 additions & 0 deletions src/services/logProfiles/schema.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
type azureLogProfileRetentionPolicy
@generate(
query: { get: false, query: true, aggregate: false }
mutation: { add: false, delete: false }
subscription: false
) {
enabled: Boolean @search
days: Int @search
}

type azureLogProfile implements azureBaseResource
@generate(
query: { get: true, query: true, aggregate: true }
mutation: { add: true, delete: false }
)
@key(fields: "id") {
region: String @search(by: [hash, regexp])
subscriptionId: String @search(by: [hash, regexp])
storageAccountId: String @search(by: [hash, regexp])
serviceBusRuleId: String @search(by: [hash, regexp])
locations: [String] @search(by: [hash, regexp])
categories: [String] @search(by: [hash, regexp])
retentionPolicy: azureLogProfileRetentionPolicy
tags: [azureRawTag]
storageAccount: [azureStorageAccount] @hasInverse(field: logProfiles)
}
1 change: 1 addition & 0 deletions src/services/storageAccount/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -239,4 +239,5 @@ type azureStorageAccount implements azureResource
eventHubs: [azureEventHub] @hasInverse(field: storageAccount)
diagnosticSettings: [azureDiagnosticSetting] @hasInverse(field: storageAccount)
fileShares: [azureFileShare] @hasInverse(field: storageAccount)
logProfiles: [azureLogProfile] @hasInverse(field: storageAccount)
}
25 changes: 25 additions & 0 deletions src/services/tag/connections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1197,6 +1197,31 @@ export default ({
}
}
}

/**
* Find related Log Profiles
*/
const logProfiles: {
name: string
data: { [property: string]: any[] }
} = data.find(({ name }) => name === services.logProfiles)
if (logProfiles?.data?.[region]) {
const dataAtRegion: any = findServiceInstancesWithTag(
tag,
logProfiles.data[region]
)
if (!isEmpty(dataAtRegion)) {
for (const logProfile of dataAtRegion) {
const { id } = logProfile
connections.push({
id,
resourceType: services.logProfiles,
relation: 'child',
field: 'logProfiles',
})
}
}
}
}

const tagResult = {
Expand Down
1 change: 1 addition & 0 deletions src/services/tag/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type azureTag @key(fields: "id") {
loadBalancers: [azureLoadBalancer]
logAnalyticsSolutions: [azureLogAnalyticsSolution]
logAnalyticsWorkspaces: [azureLogAnalyticsWorkspace]
logProfiles: [azureLogProfile]
machineLearningWorkspaces: [azureMachineLearningWorkspace]
metricAlerts: [azureMetricAlert]
mySqlServers: [azureMySqlServer]
Expand Down
19 changes: 19 additions & 0 deletions src/types/generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3131,6 +3131,23 @@ export type AzureLogAnalyticsWorkspaceSku = {
name: Scalars['String'];
};

export type AzureLogProfile = AzureBaseResource & {
categories?: Maybe<Array<Maybe<Scalars['String']>>>;
locations?: Maybe<Array<Maybe<Scalars['String']>>>;
region?: Maybe<Scalars['String']>;
retentionPolicy?: Maybe<AzureLogProfileRetentionPolicy>;
serviceBusRuleId?: Maybe<Scalars['String']>;
storageAccount?: Maybe<Array<Maybe<AzureStorageAccount>>>;
storageAccountId?: Maybe<Scalars['String']>;
subscriptionId?: Maybe<Scalars['String']>;
tags?: Maybe<Array<Maybe<AzureRawTag>>>;
};

export type AzureLogProfileRetentionPolicy = {
days?: Maybe<Scalars['Int']>;
enabled?: Maybe<Scalars['Boolean']>;
};

export type AzureMachineLearningWorkspace = AzureResource & {
allowPublicAccessWhenBehindVnet?: Maybe<Scalars['Boolean']>;
applicationInsights?: Maybe<Scalars['String']>;
Expand Down Expand Up @@ -4405,6 +4422,7 @@ export type AzureStorageAccount = AzureResource & {
keyPolicyExpirationPeriodInDays?: Maybe<Scalars['Int']>;
largeFileSharesState?: Maybe<Scalars['String']>;
lastGeoFailoverTime?: Maybe<Scalars['String']>;
logProfiles?: Maybe<Array<Maybe<AzureLogProfile>>>;
minimumTlsVersion?: Maybe<Scalars['String']>;
networkRuleIpRules?: Maybe<Array<Maybe<AzureStorageAccountIpRule>>>;
networkRuleResourceAccessRules?: Maybe<Array<Maybe<AzureStorageAccountResourceAccessRule>>>;
Expand Down Expand Up @@ -4868,6 +4886,7 @@ export type AzureTag = {
loadBalancers?: Maybe<Array<Maybe<AzureLoadBalancer>>>;
logAnalyticsSolutions?: Maybe<Array<Maybe<AzureLogAnalyticsSolution>>>;
logAnalyticsWorkspaces?: Maybe<Array<Maybe<AzureLogAnalyticsWorkspace>>>;
logProfiles?: Maybe<Array<Maybe<AzureLogProfile>>>;
machineLearningWorkspaces?: Maybe<Array<Maybe<AzureMachineLearningWorkspace>>>;
metricAlerts?: Maybe<Array<Maybe<AzureMetricAlert>>>;
mySqlServers?: Maybe<Array<Maybe<AzureMySqlServer>>>;
Expand Down

0 comments on commit e593788

Please sign in to comment.