Пример #1
0
def _load_db_threat_detection_policies(
        neo4j_session: neo4j.Session, threat_detection_policies: List[Dict], update_tag: int,
) -> None:
    """
    Ingest threat detection policy into neo4j.
    """
    ingest_threat_detection_policies = """
    UNWIND {threat_detection_policies_list} as tdp
    MERGE (policy:AzureDatabaseThreatDetectionPolicy{id: tdp.id})
    ON CREATE SET policy.firstseen = timestamp(),
    policy.location = tdp.location
    SET policy.name = tdp.name,
    policy.location = tdp.location,
    policy.kind = tdp.kind,
    policy.emailadmins = tdp.email_account_admins,
    policy.emailaddresses = tdp.email_addresses,
    policy.retentiondays = tdp.retention_days,
    policy.state = tdp.state,
    policy.storageendpoint = tdp.storage_endpoint,
    policy.useserverdefault = tdp.use_server_default,
    policy.disabledalerts = tdp.disabled_alerts,
    policy.lastupdated = {azure_update_tag}
    WITH policy, tdp
    MATCH (d:AzureSQLDatabase{id: tdp.database_id})
    MERGE (d)-[r:CONTAINS]->(policy)
    ON CREATE SET r.firstseen = timestamp()
    SET r.lastupdated = {azure_update_tag}
    """

    neo4j_session.run(
        ingest_threat_detection_policies,
        threat_detection_policies_list=threat_detection_policies,
        azure_update_tag=update_tag,
    )
def load_load_balancer_v2_target_groups(
    neo4j_session: neo4j.Session, load_balancer_id: str, target_groups: List[Dict], current_aws_account_id: str,
    update_tag: int,
) -> None:
    ingest_instances = """
    MATCH (elbv2:LoadBalancerV2{id: {ID}}), (instance:EC2Instance{instanceid: {INSTANCE_ID}})
    MERGE (elbv2)-[r:EXPOSE]->(instance)
    ON CREATE SET r.firstseen = timestamp()
    SET r.lastupdated = {update_tag}
    WITH instance
    MATCH (aa:AWSAccount{id: {AWS_ACCOUNT_ID}})
    MERGE (aa)-[r:RESOURCE]->(instance)
    ON CREATE SET r.firstseen = timestamp()
    SET r.lastupdated = {update_tag}
    """
    for target_group in target_groups:

        if not target_group['TargetType'] == 'instance':
            # Only working on EC2 Instances now. TODO: Add IP & Lambda EXPOSE.
            continue

        for instance in target_group["Targets"]:
            neo4j_session.run(
                ingest_instances,
                ID=load_balancer_id,
                INSTANCE_ID=instance,
                AWS_ACCOUNT_ID=current_aws_account_id,
                update_tag=update_tag,
            )
Пример #3
0
def load_github_owners(neo4j_session: neo4j.Session, update_tag: int,
                       repo_owners: List[Dict]) -> None:
    """
    Ingest the relationships for repo owners
    :param neo4j_session: Neo4J session object for server communication
    :param update_tag: Timestamp used to determine data freshness
    :param repo_owners: list of owner to repo mappings
    :return: Nothing
    """
    for owner in repo_owners:
        ingest_owner_template = Template("""
            MERGE (user:$account_type{id: {Id}})
            ON CREATE SET user.firstseen = timestamp()
            SET user.username = {UserName},
            user.lastupdated = {UpdateTag}
            WITH user

            MATCH (repo:GitHubRepository{id: {RepoId}})
            MERGE (user)<-[r:OWNER]-(repo)
            ON CREATE SET r.firstseen = timestamp()
            SET r.lastupdated = {UpdateTag}""")

        account_type = {
            'User': "******",
            'Organization': "GitHubOrganization"
        }

        neo4j_session.run(
            ingest_owner_template.safe_substitute(
                account_type=account_type[owner['type']]),
            Id=owner['owner_id'],
            UserName=owner['owner'],
            RepoId=owner['repo_id'],
            UpdateTag=update_tag,
        )
Пример #4
0
def load_organization_users(
    neo4j_session: neo4j.Session, user_data: List[Dict], org_data: Dict,
    update_tag: int,
) -> None:
    query = """
    MERGE (org:GitHubOrganization{id: {OrgUrl}})
    ON CREATE SET org.firstseen = timestamp()
    SET org.username = {OrgLogin},
    org.lastupdated = {UpdateTag}
    WITH org

    UNWIND {UserData} as user

    MERGE (u:GitHubUser{id: user.node.url})
    ON CREATE SET u.firstseen = timestamp()
    SET u.fullname = user.node.name,
    u.username = user.node.login,
    u.has_2fa_enabled = user.hasTwoFactorEnabled,
    u.role = user.role,
    u.is_site_admin = user.node.isSiteAdmin,
    u.email = user.node.email,
    u.company = user.node.company,
    u.lastupdated = {UpdateTag}

    MERGE (u)-[r:MEMBER_OF]->(org)
    ON CREATE SET r.firstseen = timestamp()
    SET r.lastupdated = {UpdateTag}
    """
    neo4j_session.run(
        query,
        OrgUrl=org_data['url'],
        OrgLogin=org_data['login'],
        UserData=user_data,
        UpdateTag=update_tag,
    )
Пример #5
0
def _load_kms_key_grants(neo4j_session: neo4j.Session, grants_list: List[Dict],
                         update_tag: int) -> None:
    """
    Ingest KMS Key Grants into neo4j.
    """
    ingest_grants = """
    UNWIND {grants} AS grant
    MERGE (g:KMSGrant{id: grant.GrantId})
    ON CREATE SET g.firstseen = timestamp(), g.granteeprincipal = grant.GranteePrincipal,
    g.creationdate = grant.CreationDate
    SET g.name = grant.GrantName, g.lastupdated = {UpdateTag}
    WITH g, grant
    MATCH (kmskey:KMSKey{id: grant.KeyId})
    MERGE (g)-[r:APPLIED_ON]->(kmskey)
    ON CREATE SET r.firstseen = timestamp()
    SET r.lastupdated = {UpdateTag}
    """

    # neo4j does not accept datetime objects and values. This loop is used to convert
    # these values to string.
    for grant in grants_list:
        grant['CreationDate'] = str(grant['CreationDate'])

    neo4j_session.run(
        ingest_grants,
        grants=grants_list,
        UpdateTag=update_tag,
    )
Пример #6
0
def _load_okta_group_to_aws_roles(
    neo4j_session: neo4j.Session,
    group_to_role: List[Dict],
    okta_update_tag: int,
) -> None:
    """
    Add the ALLOWED_BY relationship between OktaGroups and the AWSRoles they enable
    :param neo4j_session: session with the Neo4j server
    :param group_to_role: the mapping between OktaGroups and the AWSRoles they allow access to
    :param okta_update_tag: The timestamp value to set our new Neo4j resources with
    :return: Nothing
    """
    ingest_statement = """

    UNWIND {GROUP_TO_ROLE} as app_data
    MATCH (role:AWSRole{arn: app_data.role})
    MATCH (group:OktaGroup{id: app_data.groupid})
    MERGE (role)<-[r:ALLOWED_BY]-(group)
    ON CREATE SET r.firstseen = timestamp()
    SET r.lastupdated = {okta_update_tag}
    """

    neo4j_session.run(
        ingest_statement,
        GROUP_TO_ROLE=group_to_role,
        okta_update_tag=okta_update_tag,
    )
Пример #7
0
def _load_apigateway_resources(
    neo4j_session: neo4j.Session,
    resources: List,
    update_tag: int,
) -> None:
    """
    Ingest the API Gateway Resource details into neo4j.
    """
    ingest_resources = """
    UNWIND {resources_list} AS res
    MERGE (s:APIGatewayResource{id: res.id})
    ON CREATE SET s.firstseen = timestamp()
    SET s.path = res.path,
    s.pathpart = res.pathPart,
    s.parentid = res.parentId,
    s.lastupdated ={UpdateTag}
    WITH s, res
    MATCH (rest_api:APIGatewayRestAPI{id: res.apiId})
    MERGE (rest_api)-[r:RESOURCE]->(s)
    ON CREATE SET r.firstseen = timestamp()
    SET r.lastupdated = {UpdateTag}
    """

    neo4j_session.run(
        ingest_resources,
        resources_list=resources,
        UpdateTag=update_tag,
    )
Пример #8
0
def load_ec2_key_pairs(
    neo4j_session: neo4j.Session,
    data: List[Dict],
    region: str,
    current_aws_account_id: str,
    update_tag: int,
) -> None:
    ingest_key_pair = """
    MERGE (keypair:KeyPair:EC2KeyPair{arn: {ARN}, id: {ARN}})
    ON CREATE SET keypair.firstseen = timestamp()
    SET keypair.keyname = {KeyName}, keypair.keyfingerprint = {KeyFingerprint}, keypair.region = {Region},
    keypair.lastupdated = {update_tag}
    WITH keypair
    MATCH (aa:AWSAccount{id: {AWS_ACCOUNT_ID}})
    MERGE (aa)-[r:RESOURCE]->(keypair)
    ON CREATE SET r.firstseen = timestamp()
    SET r.lastupdated = {update_tag}
    """

    for key_pair in data:
        key_name = key_pair["KeyName"]
        key_fingerprint = key_pair.get("KeyFingerprint")
        key_pair_arn = f'arn:aws:ec2:{region}:{current_aws_account_id}:key-pair/{key_name}'

        neo4j_session.run(
            ingest_key_pair,
            ARN=key_pair_arn,
            KeyName=key_name,
            KeyFingerprint=key_fingerprint,
            AWS_ACCOUNT_ID=current_aws_account_id,
            Region=region,
            update_tag=update_tag,
        )
Пример #9
0
def load_ecr_repositories(
    neo4j_session: neo4j.Session,
    repos: List[Dict],
    region: str,
    current_aws_account_id: str,
    aws_update_tag: int,
) -> None:
    query = """
    UNWIND {Repositories} as ecr_repo
        MERGE (repo:ECRRepository{id: ecr_repo.repositoryArn})
        ON CREATE SET repo.firstseen = timestamp(),
            repo.arn = ecr_repo.repositoryArn,
            repo.name = ecr_repo.repositoryName,
            repo.region = {Region},
            repo.created_at = ecr_repo.createdAt
        SET repo.lastupdated = {aws_update_tag},
            repo.uri = ecr_repo.repositoryUri
        WITH repo

        MATCH (owner:AWSAccount{id: {AWS_ACCOUNT_ID}})
        MERGE (owner)-[r:RESOURCE]->(repo)
        ON CREATE SET r.firstseen = timestamp()
        SET r.lastupdated = {aws_update_tag}
    """
    logger.debug("Loading ECR repositories for region '%s' into graph.",
                 region)
    neo4j_session.run(
        query,
        Repositories=repos,
        Region=region,
        aws_update_tag=aws_update_tag,
        AWS_ACCOUNT_ID=current_aws_account_id,
    ).consume()  # See issue #440
Пример #10
0
def load_s3_buckets(neo4j_session: neo4j.Session, data: Dict,
                    current_aws_account_id: str, aws_update_tag: int) -> None:
    ingest_bucket = """
    MERGE (bucket:S3Bucket{id:{BucketName}})
    ON CREATE SET bucket.firstseen = timestamp(), bucket.creationdate = {CreationDate}
    SET bucket.name = {BucketName}, bucket.region = {BucketRegion}, bucket.arn = {Arn},
    bucket.lastupdated = {aws_update_tag}
    WITH bucket
    MATCH (owner:AWSAccount{id: {AWS_ACCOUNT_ID}})
    MERGE (owner)-[r:RESOURCE]->(bucket)
    ON CREATE SET r.firstseen = timestamp()
    SET r.lastupdated = {aws_update_tag}
    """

    # The owner data returned by the API maps to the aws account nickname and not the IAM user
    # there doesn't seem to be a way to retreive the mapping but we can get the current context account
    # so we map to that directly

    for bucket in data["Buckets"]:
        arn = "arn:aws:s3:::" + bucket["Name"]
        neo4j_session.run(
            ingest_bucket,
            BucketName=bucket["Name"],
            BucketRegion=bucket["Region"],
            Arn=arn,
            CreationDate=str(bucket["CreationDate"]),
            AWS_ACCOUNT_ID=current_aws_account_id,
            aws_update_tag=aws_update_tag,
        )
Пример #11
0
def _load_okta_group_members(
    neo4j_session: neo4j.Session,
    group_id: str,
    member_list: List[str],
    okta_update_tag: int,
) -> None:
    """
    Add group membership data into the graph
    :param neo4j_session: session with the Neo4j server
    :param group_id: group id to map
    :param member_list: group members
    :param okta_update_tag: The timestamp value to set our new Neo4j resources with
    :return: Nothing
    """
    ingest = """
    MATCH (group:OktaGroup{id: {GROUP_ID}})
    WITH group
    UNWIND {MEMBER_LIST} as member_id
    MATCH (user:OktaUser{id: member_id})
    WITH group, user
    MERGE (user)-[r:MEMBER_OF_OKTA_GROUP]->(group)
    ON CREATE SET r.firstseen = timestamp()
    SET r.lastupdated = {okta_update_tag}
    """

    neo4j_session.run(
        ingest,
        GROUP_ID=group_id,
        MEMBER_LIST=member_list,
        okta_update_tag=okta_update_tag,
    )
Пример #12
0
def _load_s3_acls(neo4j_session: neo4j.Session, acls: Dict,
                  aws_account_id: str, update_tag: int) -> None:
    """
    Ingest S3 ACL into neo4j.
    """
    ingest_acls = """
    UNWIND {acls} AS acl
    MERGE (a:S3Acl{id: acl.id})
    ON CREATE SET a.firstseen = timestamp(), a.owner = acl.owner, a.ownerid = acl.ownerid, a.type = acl.type,
    a.displayname = acl.displayname, a.granteeid = acl.granteeid, a.uri = acl.uri, a.permission = acl.permission
    SET a.lastupdated = {UpdateTag}
    WITH a,acl MATCH (s3:S3Bucket{id: acl.bucket})
    MERGE (a)-[r:APPLIES_TO]->(s3)
    ON CREATE SET r.firstseen = timestamp()
    SET r.lastupdated = {UpdateTag}
    """

    neo4j_session.run(
        ingest_acls,
        acls=acls,
        UpdateTag=update_tag,
    )

    # implement the acl permission
    # https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#permissions
    run_analysis_job(
        'aws_s3acl_analysis.json',
        neo4j_session,
        {'AWS_ID': aws_account_id},
    )
Пример #13
0
def _load_transparent_data_encryptions(
        neo4j_session: neo4j.Session, encryptions_list: List[Dict], update_tag: int,
) -> None:
    """
    Ingest transparent data encryptions into neo4j.
    """
    ingest_data_encryptions = """
    UNWIND {transparent_data_encryptions_list} as e
    MERGE (tae:AzureTransparentDataEncryption{id: e.id})
    ON CREATE SET tae.firstseen = timestamp(),
    tae.location = e.location
    SET tae.name = e.name,
    tae.status = e.status,
    tae.lastupdated = {azure_update_tag}
    WITH tae, e
    MATCH (d:AzureSQLDatabase{id: e.database_id})
    MERGE (d)-[r:CONTAINS]->(tae)
    ON CREATE SET r.firstseen = timestamp()
    SET r.lastupdated = {azure_update_tag}
    """

    neo4j_session.run(
        ingest_data_encryptions,
        transparent_data_encryptions_list=encryptions_list,
        azure_update_tag=update_tag,
    )
Пример #14
0
def _load_restore_points(
        neo4j_session: neo4j.Session, restore_points: List[Dict], update_tag: int,
) -> None:
    """
    Ingest restore points into neo4j.
    """
    ingest_restore_points = """
    UNWIND {restore_points_list} as rp
    MERGE (point:AzureRestorePoint{id: rp.id})
    ON CREATE SET point.firstseen = timestamp(),
    point.location = rp.location
    SET point.name = rp.name,
    point.restoredate = rp.earliest_restore_date,
    point.restorepointtype = rp.restore_point_type,
    point.creationdate = rp.restore_point_creation_date,
    point.lastupdated = {azure_update_tag}
    WITH point, rp
    MATCH (d:AzureSQLDatabase{id: rp.database_id})
    MERGE (d)-[r:CONTAINS]->(point)
    ON CREATE SET r.firstseen = timestamp()
    SET r.lastupdated = {azure_update_tag}
    """

    neo4j_session.run(
        ingest_restore_points,
        restore_points_list=restore_points,
        azure_update_tag=update_tag,
    )
def load_network_interface_instance_relations(
    neo4j_session: neo4j.Session,
    instance_associations: List[Dict],
    region: str,
    aws_account_id: str,
    update_tag: int,
) -> None:
    """
    Creates (:EC2Instance)-[:NETWORK_INTERFACE]->(:NetworkInterface)
    """
    ingest_network_interface_instance_relations = """
    UNWIND {instance_associations} AS instance_association
        MATCH (netinf:NetworkInterface{id: instance_association.netinf_id}),
            (instance:EC2Instance{id: instance_association.instance_id})
        MERGE (instance)-[r:NETWORK_INTERFACE]->(netinf)
        ON CREATE SET r.firstseen = timestamp()
        SET r.lastupdated = {update_tag}
    """
    logger.debug("Attaching %d EC2 instances to network interfaces in %s.",
                 len(instance_associations), region)
    neo4j_session.run(
        ingest_network_interface_instance_relations,
        instance_associations=instance_associations,
        update_tag=update_tag,
        region=region,
        aws_account_id=aws_account_id,
    )
Пример #16
0
def load_snapshots(
        neo4j_session: neo4j.Session, data: List[Dict], region: str, current_aws_account_id: str, update_tag: int,
) -> None:
    ingest_snapshots = """
    UNWIND {snapshots_list} as snapshot
        MERGE (s:EBSSnapshot{id: snapshot.SnapshotId})
        ON CREATE SET s.firstseen = timestamp()
        SET s.lastupdated = {update_tag}, s.description = snapshot.Description, s.encrypted = snapshot.Encrypted,
        s.progress = snapshot.Progress, s.starttime = snapshot.StartTime, s.state = snapshot.State,
        s.statemessage = snapshot.StateMessage, s.volumeid = snapshot.VolumeId, s.volumesize = snapshot.VolumeSize,
        s.outpostarn = snapshot.OutpostArn, s.dataencryptionkeyid = snapshot.DataEncryptionKeyId,
        s.kmskeyid = snapshot.KmsKeyId, s.region={Region}
        WITH s
        MATCH (aa:AWSAccount{id: {AWS_ACCOUNT_ID}})
        MERGE (aa)-[r:RESOURCE]->(s)
        ON CREATE SET r.firstseen = timestamp()
        SET r.lastupdated = {update_tag}
    """

    for snapshot in data:
        snapshot['StartTime'] = str(snapshot['StartTime'])

    neo4j_session.run(
        ingest_snapshots,
        snapshots_list=data,
        AWS_ACCOUNT_ID=current_aws_account_id,
        Region=region,
        update_tag=update_tag,
    )
def load_network_interface_elbv2_relations(
    neo4j_session: neo4j.Session,
    elb_associations_v2: List[Dict],
    region: str,
    aws_account_id: str,
    update_tag: int,
) -> None:
    """
    Creates (:LoadBalancerV2)-[:NETWORK_INTERFACE]->(:NetworkInterface)
    """
    ingest_network_interface_elb2_relations = """
    UNWIND {elb_associations} AS elb_association
        MATCH (netinf:NetworkInterface{id: elb_association.netinf_id}),
            (elb:LoadBalancerV2{id: elb_association.elb_id})
        MERGE (elb)-[r:NETWORK_INTERFACE]->(netinf)
        ON CREATE SET r.firstseen = timestamp()
        SET r.lastupdated = {update_tag}
    """
    logger.debug("Attaching %d ELB V2s to network interfaces in %s.",
                 len(elb_associations_v2), region)
    neo4j_session.run(
        ingest_network_interface_elb2_relations,
        elb_associations=elb_associations_v2,
        update_tag=update_tag,
        region=region,
        aws_account_id=aws_account_id,
    )
Пример #18
0
def load_snapshot_volume_relations(
        neo4j_session: neo4j.Session, data: List[Dict], current_aws_account_id: str, update_tag: int,
) -> None:
    ingest_volumes = """
    UNWIND {snapshot_volumes_list} as volume
        MERGE (v:EBSVolume{id: volume.VolumeId})
        ON CREATE SET v.firstseen = timestamp()
        SET v.lastupdated = {update_tag}
        WITH v, volume
        MATCH (aa:AWSAccount{id: {AWS_ACCOUNT_ID}})
        MERGE (aa)-[r:RESOURCE]->(v)
        ON CREATE SET r.firstseen = timestamp()
        SET r.lastupdated = {update_tag}
        WITH v, volume
        MATCH (s:EBSSnapshot{id: volume.SnapshotId})
        MERGE (s)-[r:CREATED_FROM]->(v)
        ON CREATE SET r.firstseen = timestamp()
        SET r.lastupdated = {update_tag}
    """

    neo4j_session.run(
        ingest_volumes,
        snapshot_volumes_list=data,
        AWS_ACCOUNT_ID=current_aws_account_id,
        update_tag=update_tag,
    )
Пример #19
0
def _load_apigateway_certificates(
    neo4j_session: neo4j.Session,
    certificates: List,
    update_tag: int,
) -> None:
    """
    Ingest the API Gateway Client Certificate details into neo4j.
    """
    ingest_certificates = """
    UNWIND {certificates_list} as certificate
    MERGE (c:APIGatewayClientCertificate{id: certificate.clientCertificateId})
    ON CREATE SET c.firstseen = timestamp(), c.createddate = certificate.createdDate
    SET c.lastupdated = {UpdateTag}, c.expirationdate = certificate.expirationDate
    WITH c, certificate
    MATCH (stage:APIGatewayStage{id: certificate.stageArn})
    MERGE (stage)-[r:HAS_CERTIFICATE]->(c)
    ON CREATE SET r.firstseen = timestamp()
    SET r.lastupdated = {UpdateTag}
    """

    # neo4j does not accept datetime objects and values. This loop is used to convert
    # these values to string.
    for certificate in certificates:
        certificate['createdDate'] = str(certificate['createdDate'])
        certificate['expirationDate'] = str(certificate.get('expirationDate'))
        certificate['stageArn'] = "arn:aws:apigateway:::" + certificate[
            'apiId'] + "/" + certificate['stageName']

    neo4j_session.run(
        ingest_certificates,
        certificates_list=certificates,
        UpdateTag=update_tag,
    )
Пример #20
0
def _load_user_role(neo4j_session: neo4j.Session, user_id: str,
                    roles_data: List[Dict], okta_update_tag: int) -> None:
    ingest = """
    MATCH (user:OktaUser{id: {USER_ID}})<-[:RESOURCE]-(org:OktaOrganization)
    WITH user,org
    UNWIND {ROLES_DATA} as role_data
    MERGE (role_node:OktaAdministrationRole{id: role_data.type})
    ON CREATE SET role_node.type = role_data.type, role_node.firstseen = timestamp()
    SET role_node.label = role_data.label, role_node.lastupdated = {okta_update_tag}
    WITH user, role_node, org
    MERGE (user)-[r:MEMBER_OF_OKTA_ROLE]->(role_node)
    ON CREATE SET r.firstseen = timestamp()
    SET r.lastupdated = {okta_update_tag}
    WITH role_node, org
    MERGE (org)-[r2:RESOURCE]->(role_node)
    ON CREATE SET r2.firstseen = timestamp()
    SET r2.lastupdated = {okta_update_tag}
    """

    neo4j_session.run(
        ingest,
        USER_ID=user_id,
        ROLES_DATA=roles_data,
        okta_update_tag=okta_update_tag,
    )
Пример #21
0
def load_load_balancer_listeners(
    neo4j_session: neo4j.Session,
    load_balancer_id: str,
    listener_data: List[Dict],
    update_tag: int,
) -> None:
    ingest_listener = """
    MATCH (elb:LoadBalancer{id: {LoadBalancerId}})
    WITH elb
    UNWIND {Listeners} as data
        MERGE (l:Endpoint:ELBListener{id: elb.id + toString(data.Listener.LoadBalancerPort) +
                toString(data.Listener.Protocol)})
        ON CREATE SET l.port = data.Listener.LoadBalancerPort, l.protocol = data.Listener.Protocol,
        l.firstseen = timestamp()
        SET l.instance_port = data.Listener.InstancePort, l.instance_protocol = data.Listener.InstanceProtocol,
        l.policy_names = data.PolicyNames,
        l.lastupdated = {update_tag}
        WITH l, elb
        MERGE (elb)-[r:ELB_LISTENER]->(l)
        ON CREATE SET r.firstseen = timestamp()
        SET r.lastupdated = {update_tag}
    """

    neo4j_session.run(
        ingest_listener,
        LoadBalancerId=load_balancer_id,
        Listeners=listener_data,
        update_tag=update_tag,
    )
Пример #22
0
def load_dynamodb_tables(
    neo4j_session: neo4j.Session, data: List[Dict], region: str, current_aws_account_id: str,
    aws_update_tag: int,
) -> None:
    ingest_table = """
    MERGE (table:DynamoDBTable{id: {Arn}})
    ON CREATE SET table.firstseen = timestamp(), table.arn = {Arn}, table.name = {TableName},
    table.region = {Region}
    SET table.lastupdated = {aws_update_tag}, table.rows = {Rows}, table.size = {Size},
    table.provisioned_throughput_read_capacity_units = {ProvisionedThroughputReadCapacityUnits},
    table.provisioned_throughput_write_capacity_units = {ProvisionedThroughputWriteCapacityUnits}
    WITH table
    MATCH (owner:AWSAccount{id: {AWS_ACCOUNT_ID}})
    MERGE (owner)-[r:RESOURCE]->(table)
    ON CREATE SET r.firstseen = timestamp()
    SET r.lastupdated = {aws_update_tag}
    """

    for table in data:
        neo4j_session.run(
            ingest_table,
            Arn=table['Table']['TableArn'],
            Region=region,
            ProvisionedThroughputReadCapacityUnits=table['Table']['ProvisionedThroughput']['ReadCapacityUnits'],
            ProvisionedThroughputWriteCapacityUnits=table['Table']['ProvisionedThroughput']['WriteCapacityUnits'],
            Size=table['Table']['TableSizeBytes'],
            TableName=table['Table']['TableName'],
            Rows=table['Table']['ItemCount'],
            AWS_ACCOUNT_ID=current_aws_account_id,
            aws_update_tag=aws_update_tag,
        )
        load_gsi(neo4j_session, table, region, current_aws_account_id, aws_update_tag)
Пример #23
0
def _load_lambda_event_source_mappings(
    neo4j_session: neo4j.Session,
    lambda_event_source_mappings: List[Dict],
    update_tag: int,
) -> None:
    ingest_esms = """
    UNWIND {esm_list} AS esm
        MERGE (e:AWSLambdaEventSourceMapping{id: esm.UUID})
        ON CREATE SET e.firstseen = timestamp()
        SET e.batchsize = esm.BatchSize,
        e.startingposition = esm.StartingPosition,
        e.startingpositiontimestamp = esm.StartingPositionTimestamp,
        e.parallelizationfactor = esm.ParallelizationFactor,
        e.maximumbatchingwindowinseconds = esm.MaximumBatchingWindowInSeconds,
        e.eventsourcearn = esm.EventSourceArn,
        e.lastmodified = esm.LastModified,
        e.lastprocessingresult = esm.LastProcessingResult,
        e.state = esm.State,
        e.maximumrecordage = esm.MaximumRecordAgeInSeconds,
        e.bisectbatchonfunctionerror = esm.BisectBatchOnFunctionError,
        e.maximumretryattempts = esm.MaximumRetryAttempts,
        e.tumblingwindowinseconds = esm.TumblingWindowInSeconds,
        e.lastupdated = {aws_update_tag}
        WITH e, esm
        MATCH (lambda:AWSLambda{id: esm.FunctionArn})
        MERGE (lambda)-[r:RESOURCE]->(e)
        ON CREATE SET r.firstseen = timestamp()
        SET r.lastupdated = {aws_update_tag}
    """

    neo4j_session.run(
        ingest_esms,
        esm_list=lambda_event_source_mappings,
        aws_update_tag=update_tag,
    )
Пример #24
0
def load_gsi(
    neo4j_session: neo4j.Session, table: Dict, region: str, current_aws_account_id: str,
    aws_update_tag: int,
) -> None:
    ingest_gsi = """
    MERGE (gsi:DynamoDBGlobalSecondaryIndex{id: {Arn}})
    ON CREATE SET gsi.firstseen = timestamp(), gsi.arn = {Arn}, gsi.name = {GSIName},
    gsi.region = {Region}
    SET gsi.lastupdated = {aws_update_tag},
    gsi.provisioned_throughput_read_capacity_units = {ProvisionedThroughputReadCapacityUnits},
    gsi.provisioned_throughput_write_capacity_units = {ProvisionedThroughputWriteCapacityUnits}
    WITH gsi
    MATCH (table:DynamoDBTable{arn: {TableArn}})
    MERGE (table)-[r:GLOBAL_SECONDARY_INDEX]->(gsi)
    ON CREATE SET r.firstseen = timestamp()
    SET r.lastupdated = {aws_update_tag}
    """

    for gsi in table['Table'].get('GlobalSecondaryIndexes', []):
        neo4j_session.run(
            ingest_gsi,
            TableArn=table['Table']['TableArn'],
            Arn=gsi['IndexArn'],
            Region=region,
            ProvisionedThroughputReadCapacityUnits=gsi['ProvisionedThroughput']['ReadCapacityUnits'],
            ProvisionedThroughputWriteCapacityUnits=gsi['ProvisionedThroughput']['WriteCapacityUnits'],
            GSIName=gsi['IndexName'],
            AWS_ACCOUNT_ID=current_aws_account_id,
            aws_update_tag=aws_update_tag,
        )
Пример #25
0
def load_tags(
    neo4j_session: neo4j.Session,
    tag_data: Dict,
    resource_type: str,
    region: str,
    aws_update_tag: int,
) -> None:
    INGEST_TAG_TEMPLATE = Template("""
    UNWIND {TagData} as tag_mapping
        UNWIND tag_mapping.Tags as input_tag
            MATCH (resource:$resource_label{$property:tag_mapping.resource_id})
            MERGE(aws_tag:AWSTag:Tag{id:input_tag.Key + ":" + input_tag.Value})
            ON CREATE SET aws_tag.firstseen = timestamp()

            SET aws_tag.lastupdated = {UpdateTag},
            aws_tag.key = input_tag.Key,
            aws_tag.value =  input_tag.Value,
            aws_tag.region = {Region}

            MERGE (resource)-[r:TAGGED]->(aws_tag)
            SET r.lastupdated = {UpdateTag},
            r.firstseen = timestamp()
    """)
    query = INGEST_TAG_TEMPLATE.safe_substitute(
        resource_label=TAG_RESOURCE_TYPE_MAPPINGS[resource_type]['label'],
        property=TAG_RESOURCE_TYPE_MAPPINGS[resource_type]['property'],
    )
    neo4j_session.run(
        query,
        TagData=tag_data,
        UpdateTag=aws_update_tag,
        Region=region,
    )
Пример #26
0
def _attach_target_tags(neo4j_session: neo4j.Session, fw: Resource,
                        gcp_update_tag: int) -> None:
    """
    Attach target tags to the firewall object
    :param neo4j_session: The neo4j session
    :param fw: The firewall object
    :param gcp_update_tag: The timestamp
    :return: Nothing
    """
    query = """
    MATCH (fw:GCPFirewall{id:{FwPartialUri}})

    MERGE (t:GCPNetworkTag{id:{TagId}})
    ON CREATE SET t.firstseen = timestamp(),
    t.tag_id = {TagId},
    t.value = {TagValue}
    SET t.lastupdated = {gcp_update_tag}

    MERGE (fw)-[h:TARGET_TAG]->(t)
    ON CREATE SET h.firstseen = timestamp()
    SET h.lastupdated = {gcp_update_tag}
    """
    for tag in fw.get('targetTags', []):
        tag_id = _create_gcp_network_tag_id(fw['vpc_partial_uri'], tag)
        neo4j_session.run(
            query,
            FwPartialUri=fw['id'],
            TagId=tag_id,
            TagValue=tag,
            gcp_update_tag=gcp_update_tag,
        )
Пример #27
0
def load_github_languages(neo4j_session: neo4j.Session, update_tag: int,
                          repo_languages: List[Dict]) -> None:
    """
    Ingest the relationships for repo languages
    :param neo4j_session: Neo4J session object for server communication
    :param update_tag: Timestamp used to determine data freshness
    :param repo_languages: list of language to repo mappings
    :return: Nothing
    """
    ingest_languages = """
        UNWIND {Languages} as lang

        MERGE (pl:ProgrammingLanguage{id: lang.language_name})
        ON CREATE SET pl.firstseen = timestamp(),
        pl.name = lang.language_name
        SET pl.lastupdated = {UpdateTag}
        WITH pl, lang

        MATCH (repo:GitHubRepository{id: lang.repo_id})
        MERGE (pl)<-[r:LANGUAGE]-(repo)
        ON CREATE SET r.firstseen = timestamp()
        SET r.lastupdated = {UpdateTag}"""

    neo4j_session.run(
        ingest_languages,
        Languages=repo_languages,
        UpdateTag=update_tag,
    )
Пример #28
0
def _attach_ec2_security_groups(neo4j_session: neo4j.Session,
                                instances: List[Dict],
                                aws_update_tag: int) -> None:
    """
    Attach an RDS instance to its EC2SecurityGroups
    """
    attach_rds_to_group = """
    UNWIND {Groups} as rds_sg
        MATCH (rds:RDSInstance{id: rds_sg.arn})
        MERGE (sg:EC2SecurityGroup{id: rds_sg.group_id})
        MERGE (rds)-[m:MEMBER_OF_EC2_SECURITY_GROUP]->(sg)
        ON CREATE SET m.firstseen = timestamp()
        SET m.lastupdated = {aws_update_tag}
    """
    groups = []
    for instance in instances:
        for group in instance['VpcSecurityGroups']:
            groups.append({
                'arn': instance['DBInstanceArn'],
                'group_id': group['VpcSecurityGroupId'],
            })
    neo4j_session.run(
        attach_rds_to_group,
        Groups=groups,
        aws_update_tag=aws_update_tag,
    )
Пример #29
0
def load_collaborators(neo4j_session: neo4j.Session, update_tag: int,
                       collaborators: Dict) -> None:
    query = Template("""
    UNWIND {UserData} as user

    MERGE (u:GitHubUser{id: user.url})
    ON CREATE SET u.firstseen = timestamp()
    SET u.fullname = user.name,
    u.username = user.login,
    u.permission = user.permission,
    u.email = user.email,
    u.company = user.company,
    u.lastupdated = {UpdateTag}

    WITH u, user
    MATCH (repo:GitHubRepository{id: user.repo_url})
    MERGE (repo)<-[o:$rel_label]-(u)
    ON CREATE SET o.firstseen = timestamp()
    SET o.lastupdated = {UpdateTag}
    """)
    for collab_type in collaborators.keys():
        relationship_label = f"OUTSIDE_COLLAB_{collab_type}"
        neo4j_session.run(
            query.safe_substitute(rel_label=relationship_label),
            UserData=collaborators[collab_type],
            UpdateTag=update_tag,
        )
Пример #30
0
def _load_replication_links(
        neo4j_session: neo4j.Session, replication_links: List[Dict], update_tag: int,
) -> None:
    """
    Ingest replication links into neo4j.
    """
    ingest_replication_links = """
    UNWIND {replication_links_list} as replication_link
    MERGE (rl:AzureReplicationLink{id: replication_link.id})
    ON CREATE SET rl.firstseen = timestamp(),
    rl.location = replication_link.location
    SET rl.name = replication_link.name,
    rl.partnerdatabase = replication_link.partner_database,
    rl.partnerlocation = replication_link.partner_location,
    rl.partnerrole = replication_link.partner_role,
    rl.partnerserver = replication_link.partner_server,
    rl.mode = replication_link.replication_mode,
    rl.state = replication_link.replication_state,
    rl.percentcomplete = replication_link.percent_complete,
    rl.role = replication_link.role,
    rl.starttime = replication_link.start_time,
    rl.terminationallowed = replication_link.is_termination_allowed,
    rl.lastupdated = {azure_update_tag}
    WITH rl, replication_link
    MATCH (d:AzureSQLDatabase{id: replication_link.database_id})
    MERGE (d)-[r:CONTAINS]->(rl)
    ON CREATE SET r.firstseen = timestamp()
    SET r.lastupdated = {azure_update_tag}
    """

    neo4j_session.run(
        ingest_replication_links,
        replication_links_list=replication_links,
        azure_update_tag=update_tag,
    )