Intel Xeon 6 Priority Cores as a Big NVIDIA GPU AI Server Feature

Post Syndicated from John Lee original https://www.servethehome.com/intel-xeon-6-priority-cores-as-a-big-nvidia-gpu-ai-server-feature/

The Intel Xeon 6 with priority cores wins big at NVIDIA but there is a lot more going on in the release than meets the eye

The post Intel Xeon 6 Priority Cores as a Big NVIDIA GPU AI Server Feature appeared first on ServeTheHome.

Седмицата (19–24 май)

Post Syndicated from Боряна Телбис original https://www.toest.bg/sedmitsata-19-24-mai/

Седмицата (19–24 май)

Дългогодишното гледане на сериали се отблагодарява, драги читатели на „Тоест“. Ето например, ако не бях гледала преди години The IT Crowd (излъчван за кратко в България като „Компютърджии“), нямаше да мога да си обясня защо ми е толкова позната ситуацията, в която къщата ти гори, а ти пускаш постове във Facebook. В случая на разкошния Морис от The IT Crowd гореше офисът, в който работеше, и той реши да напише имейл на пожарната, за да я уведоми.

В тазседмичния анализ на Емилия Милчева „За можачите, неможачите и Добрия пожарникар“ става дума точно за това: кой пали пожарите в Столичната община, кой ги гаси и има ли как да се направи така, че да не е толкова леснозапалимо положението.

Още един проблем на местното управление се разглежда в дълбочина в новия брой на „Тоест“. По темата за незаконните ромски къщи и какво всъщност трябва да се направи с тях, Светла Енчева разговаря с Мария Методиева от „Тръст за социална алтернатива“. Когато се подхожда с разбиране и грижа към подобни казуси, става ясно, че нещата не са нито черни, нито бели и няма как удобно да бъде посочен един виновен, а е добре просто всички да работят заедно, за да се свърши каквото трябва. И то не е просто да се бутнат 20 къщи, да сме наясно. 

Виновни няма и по въпроса с изчезването на звателните форми от българския език, защото отдавна май не е важно какво е правилно, а как го чувстваме. Всеки човек си има собствено схващане как иска да му „викат“, и затова останалите гледаме да се съобразяваме (освен ако много не ни дразни с претенциите си и правим точно обратното). В новия си текст „Тук ли си, Петре?“ Павлина Върбанова разсъждава къде отиват „Иване“ и „Емиле“ и дали леко стерилното „Уважаеми Мартин“ не идва на тяхно място, за да остане завинаги.

Завинаги е много дълго време, затова по-добре да не го мислим. Но тази седмица в „Тоест“ обръщаме поглед към едни отношения, които от достатъчно дълго време определят немалко геополитически процеси. Правим го с анализа на Искрен Иванов, посветен на САЩ, Израел и Турция. Накъде гледа югоизточната ни съседка и какво вижда в тази посока, може да прочетете в „Турция между САЩ и Израел. Посткемализъм или неоосманизъм?“.

Като сме отворили дума за САЩ, трябва непременно да се каже, че си имаме чисто нов бюлетин, посветен на тях. На всеки две седмици Йоанна Елми ще прави обзор на новини, процеси, хора отвъд океана и ще ги събира под шапката на „Гласовете на Америка“. „Бавната, съсредоточена и критична журналистика остава сред най-добрите антидоти срещу силно поляризираната и емоционална страна на социалните мрежи и срещу информационната война, която се води онлайн и през различни медийни източници“, както пише самата Йоанна. Затова абонирайте се за „Гласовете на Америка“ и четете брой 1, в който се прави обзор на първите 100 дни от втория мандат на Тръмп.

А в брой 101 на рубриката ни „На второ четене“ Антония Апостолова обръща внимание на „Харолд и Мод“. Остарява ли добрата стара класика, каквато е историята на героите на Колин Хигинс? Ясно е, че краткият отговор е „не“. Обосновката е в анализа на Антония, който, както обикновено, е талантливо написан и безкрайно приятен за четене.

Четене, поне на книга, е нещо, което не се е случвало на 43% от българите през 2024 г. Тази и други разкошни новини коментира Е.Т. в епизод 15 на седмичната видеорубрика в „Тоест“. Тук е моментът може би да ви честитя 24 май – Деня на българската просвета, и няма да кажа нищо повече по темата.

В края на седмицата ни напусна Асен Григоров – един от най-разпознаваемите и опитни журналисти в България. Ще го помним с точните му коментари и непогрешимия журналистически нюх. Екипът на „Тоест“ изказва сърдечни съболезнования на семейството и близките на Асен.

Implementing Federation on Amazon MQ for RabbitMQ Private Brokers

Post Syndicated from ISHITA CHAKRABORTY original https://aws.amazon.com/blogs/compute/implementing-federation-on-amazon-mq-for-rabbitmq-private-brokers/

Federation in RabbitMQ helps in message exchange and flow across multiple RabbitMQ brokers. Amazon MQ for RabbitMQ allows federated exchanges and queues via the Federation Plugin. The federation plugin enables a downstream broker to consume a message from an exchange or a queue on an upstream. This is used to connect multiple RabbitMQ brokers and provides multiple benefits like scalability, allowing to scale out the messaging infrastructure horizontally across multiple nodes or clusters. It also provides high availability for message replication across brokers for redundancy and the ability to segregate based on security or other criteria. These benefits allow federation to be used for the below use cases:

  1. Multi region deployments
  2. Hybrid cloud deployments
  3. Disaster recovery
  4. Migrating from on-premises to cloud

Currently, the federation plugin on Amazon MQ for RabbitMQ connects to publicly available upstream brokers only. This post explains how to implement federation for Amazon MQ RabbitMQ Private Brokers using Network Load Balancers (NLB). The steps allow private brokers to communicate with each other to create a distributed system.

Overview

In this solution, you will use two single-instance brokers to implement federation with private brokers.

  1. Create two Amazon Virtual Private Cloud (VPC) – one for upstream broker and one for downstream broker. Each VPC has a private and a public subnet along with internet gateway, security groups, route tables.
  2. Create Amazon MQ RabbitMQ private brokers in the private subnets of each VPC. The broker actually resides in an account that is owned by the Amazon MQ Service, in a private subnet with a Network Load Balancer (NLB) in front of it. The NLB is used to access the broker from your account using the Elastic Network Interface (ENI) associated with the VPC Endpoint for the NLB.
  3. Create a NLB pointing to the ENI for the upstream broker. The security group associated with the NLB is used to restrict traffic to only the NAT IPs associated with the downstream broker. The upstream broker that was accessible only privately will now be connected to the public internet with IP allow listing and messages will potentially transit the internet.
  4. Create an Amazon EC2 Instance in the downstream VPC in the public subnet to connect to it and setup the federation. You need the EC2 instance only for the setup and testing.
  5. Send a message to the upstream broker using the NLB endpoint, the message is also available to the downstream broker for consumption.

Prerequisites

The following are the prerequisites for this setup:

  • Access to an AWS account.
  • An AWS IAM user/Principal with the required permissions to deploy the infrastructure.

The stack creates two new VPC. Make sure that you have fewer than five VPCs in the selected region. You increase this limit using Quotas.

Deploying the solution

You will deploy the solution using AWS CloudFormation:

The high-level steps are the following:

  1. Deploy the broker CFN stack to create VPCs, subnets, internet gateway, security groups and route tables, along with the Amazon MQ RabbitMQ brokers
  2. Get the IP address of the private upstream broker created in the broker stack
  3. Open AWS support case to get the IP to allow for the NLB
  4. Create an NLB Stack with the Network Load Balancer and rules for accessing it using AWS CloudFormation
  5. Set up the federation between the Amazon MQ RabbitMQ brokers and testing the setup

This solution is available on GitHub in the AWS Samples repository.

Step 1: Deploy the AWS CloudFormation template for the broker stack

  1. Go to the CloudFormation Console and choose Create Stack. Choose With new resources (Standard) from the drop down.
  2. For Prepare template, choose an existing template and then for Specify template, choose Upload a template file and use this template file
  3. Provide a Stack name (such as BrokerStack).
  4. Update the username and CIDR Blocks provided as parameters to the stack or leave them as defaults. For ease of setup, this template uses EC2 with managed prefix lists for EC2 Instance Connect for five regions: us-east-1, us-west-1, us-west-2, eu-west-1 and ap-south-1. Add prefix lists for other regions in the template to run this cloud formation template in those regions.
  5. Choose Next and leave everything else as defaults.
  6. Choose Submit.

The broker stack deployment takes 10 -15 minutes.

The template creates two VPCs along with a private and public subnet on each VPC with internet gateway, security groups and route tables. It also creates two private brokers in each VPC along with an EC2 Instance (t2.micro) on the downstream VPC.

Step 2: Retrieve the IP Address for the private upstream broker

  1. Once the above stack creation is complete, navigate to the Outputs tab for the stack and copy the output for PrivateUpstreamBrokerEndpoints.
  2. Extract only the host name from the “PrivateUpstreamBrokerEndpoints” in the output from above.
  3. Resolve the hostname using the following commands.
    Linux or Mac

    $ dig +short {hostname}

    Windows

    C:\> nslookup {hostname}

Take note of the IP address. You will use it in later steps.

Step 3: Create a support case to get the Amazon MQ Rabbit MQ Downstream Broker NAT IPs

Create a support case with AWS Support to get the NAT IPs associated with the downstream MQ Broker. Provide the broker Amazon Resource Name (ARN) and explain your use case and the need to do federation allow listing in the description. Use this IP address to allow the Network Load Balancer to be accessed from particular IPs only.

Step 4: Deploy the AWS CloudFormation template for NLB Stack

  1. Go to the CloudFormation Console and choose Create Stack. Choose With new resources (Standard) from the drop down.
  2. For Prepare template, Choose an existing template. For Template source, choose Upload a template file and choose this template file.
  3. Choose Next.
  4. Under Specify stack details provide a Stack name (such as NLBStack).
  5. Use the IP Address from Step 2 and Step 3 above in the parameters and choose Next.
    Make sure that the NAT IP Address is a valid CIDR range like 52.0.0.1/32.
  6. Keep the rest as defaults and choose Next again
  7. Choose Submit.

The template creates a Network Load Balancer with 2 target groups and a Security Group for it and adds rules to the Upstream Default Security group.

Step 5: Configure Federation in the downstream broker

  1. Use the Upstream Broker NLB URL output from the NLBStack and replace it in the following export commands along with the Downstream Broker Uri from the output of the BrokerStack.
    export Upstream_Broker_NLB= <UpstreamBrokerNLBURL>
    export Downstream_Broker_Uri= <DownstreamBrokerURI> 

  2. From the AWS Console, search for AWS Secrets Manager and choose Secrets. You will find 2 secrets with names as DownstreamBrokerUsernamePassword and UpstreamBrokerUsernamePassword. Open one of them and choose Retrieve Secret value to get the passwords and usernames for the brokers. Repeat for the other one.
  3. Replace values for Upstream_Broker_Username, Upstream_Broker_Password, Downstream_Broker_Username and Downstream_Broker_Password in the following commands.
    ##creates federation on the private downstream broker
    curl -XPUT -d'{"value":{"uri":"amqps://Upstream_Broker_Username:Upstream_Broker_Password@'"$Upstream_Broker_NLB"':5671","expires":3600000}}' https://Downstream_Broker_Username:Downstream_Broker_Password@{$Downstream_Broker_Uri}/api/parameters/federation-upstream/%2f/my-upstream
    
    ##creates policy for federation on the private downstream broker with pattern for exchange with Test in its name
    curl -XPUT -d'{"pattern":"^Test", "definition":{"federation-upstream-set":"all"},"apply-to":"exchanges"}' https://Downstream_Broker_Username:Downstream_Broker_Password@{$Downstream_Broker_Uri}/api/policies/%2f/federate-me

  4. From the EC2 Console, select the EC2 instance created as part of the Broker Stack in Step 1. Choose Connect and login to the instance using EC2 Instance Connect. Once connected to the terminal, paste the above lines with replaced values to create the federation upstream and the policy associated with it.

Step 6: Create TestExchange and Test Queue and Bind them

  1. Run the following steps to create a test exchange, a queue, and the binding for them. Replace values for Downstream_Broker_Username and Downstream_Broker_Password.
    ##creates a test exchange on the private downstream broker
    curl -H "content-type:application/json" -XPUT -d'{"type":"fanout","durable":true}' https://Downstream_Broker_Username:Downstream_Broker_Password@{$Downstream_Broker_Uri}/api/exchanges/%2f/TestExchange
    
    ##creates a test queue on the private downstream broker
    curl -H "content-type:application/json" -XPUT -d'{"durable":true,"arguments":{"x-dead-letter-exchange":"", "x-dead-letter-routing-key": "my.queue.dead-letter"}}' https://Downstream_Broker_Username:Downstream_Broker_Password@{$Downstream_Broker_Uri}/api/queues/%2f/TestQueue
    
    ##Binds the queue to the exchange on the private downstream broker
    curl -H "content-type:application/json" -XPOST -d'{"routing_key":"","arguments":{}}' https://Downstream_Broker_Username:Downstream_Broker_Password@{$Downstream_Broker_Uri}/api/bindings/%2f/e/TestExchange/q/TestQueue

Step 7: Validate Federation Status and Test Federation between brokers

  1. Check the Federation status by running the following command while still connected to the EC2 in the same session. Replace values for Downstream_Broker_Username and Downstream_Broker_Password.
    ##check federation status on the private downstream broker and format it as JSON
    curl -XGET https://Downstream_Broker_Username:Downstream_Broker_Password@{$Downstream_Broker_Uri}/api/federation-links | python3 -m json.tool

    The output will look like the below with status as running.

    [
        {
            "node": "rabbit@localhost",
            "exchange": "TestExchange",
            "upstream_exchange": "TestExchange",
            "type": "exchange",
            "vhost": "/",
            "upstream": "my-upstream",
            "id": "5cd2293f",
            "status": "running",
            "local_connection": "<[email protected]>",
            "uri": "amqps://MyUpstreamNLB-XXXXXXXX.elb.us-east-1.amazonaws.com:5671",
    …
        }
    ]

  2. (Optional) Send a test message now. Since you restricted the Upstream Broker NLB to only receive traffic from the Downstream broker (via the IP Address received from the support case), you will need to manually allow the EC2 Public IP Address in the NLB Security Group that was created for port 443 to perform the below step. You will also need to allow the egress from EC2 to access the NLB.
    ##Send test message on the upstream broker
    curl -k -H "content-type:application/json" -XPOST -d'{"properties":{},"routing_key":"MYKEY","payload":"Hello World","payload_encoding":"string"}' https://Upstream_Broker_Username:Upstream_Broker_Password@{$Upstream_Broker_NLB}/api/exchanges/%2f/TestExchange/publish

    Once the message is sent it will show up as routed: true. This means that the message routed to the downstream broker successfully.

  3. Use the following command to validate the message on the downstream broker. This should show the payload that you sent earlier.
    ## Get message from queue on the downstream broker
    curl -H "content-type:application/json" -XPOST -d'{"ackmode":"ack_requeue_true","count":1,"encoding": "auto"}' https://Downstream_Broker_Username:Downstream_Broker_Password@{$Downstream_Broker_Uri}/api/queues/%2f/TestQueue/get

    Output:

    [
        {
            "payload_bytes": 11,
            "redelivered": true,
            "exchange": "TestExchange",
            "routing_key": "MYKEY",
            "message_count": 0,
             …
            "payload": "Hello World",
            "payload_encoding": "string"
        }
    ]

Cleanup

This section provides information for deleting various resources created as part of this post.

  1. Delete Stack NLBStack created as part of Step 4. For instructions, refer to Deleting a stack on the AWS CloudFormation console.
  2. Delete the BrokerStack created in Step 1.

Conclusion

This post explained how to implement federation for Amazon MQ RabbitMQ private brokers. You can extend this solution to RabbitMQ brokers in a cluster deployment, same as a single-instance broker. With federated exchanges, you can create a distributed system of RabbitMQ brokers to improve reliability and scalability of the messaging system. You can also use this as a template for hybrid architecture to move messages from a private on-premises broker to the cloud as explained in Migrating message driven applications to Amazon MQ for RabbitMQ. Get more details on Federation plugin from official documentation of RabbitMQ. Get more details on Amazon MQ for RabbitMQ in our developer guide.

Unlocking the power of Amazon Q Developer: Metrics-driven strategies for better AI coding

Post Syndicated from Artur Rodrigues original https://aws.amazon.com/blogs/devops/unlocking-the-power-of-amazon-q-developer-metrics-driven-strategies-for-better-ai-coding/

We believe the most successful organizations will be those that view AI not just as a tool for automation, but as a catalyst for transforming how they approach software development entirely. The real strategic advantage will come from reimagining software development processes and culture to fully leverage AI’s capabilities. This includes rethinking traditional metrics, redefining developer productivity, and creating space and cultural change for teams to experiment with new ways of working.

This powerful observation from our April 2025 blog post “How generative AI is transforming developer workflows at Amazon” is already proving true in practice. Organizations using Amazon Q Developer are actively implementing new metrics to understand how developers leverage AI features. This data-driven approach helps them identify usage patterns, uncover areas for improvement, and recognize internal champions who drive adoption. It takes time and practice to get comfortable with prompting and understand the capabilities of new tools. I have identified three question that customers ask to measure and evaluate their Amazon Q Developer adoption.

  1. How many Q Developer active users are there?
  2. How can we track usage trends?
  3. Who are our power users?

This blog post will explore the Amazon Q Developer monitoring and tracking tools, and how they can together provide a comprehensive view of developer usage, which answer the questions listed above.

Subscription Management

The Amazon Q Developer subscription console serves as your primary source for managing Q subscriptions. The How to identify inactive users of Amazon Q Developer blog details license activity, and shows how you can navigate thought the Amazon Q Developer Console, where you can download a report showing users from all AWS organization accounts, their status (active, pending, or canceled), and the last activity date. This document from our user guide, walk you through how to enabled the organization-wide visibility at your AWS Organization management account.

The table below contains an extract of the CSV file created when you click on Download total users reports from the Amazon Q Developer Subscription Console page.

Name Subscription type Subscription status Identity provider user ID Last activity date
anakin Group Pending 14a81418-b0b1-70b7-c73a N/A
artur Group Active 34a87408-6091-7054-4b60 May 11 2025
ashoka Individual Pending 64d8a448-9021-7020-c73d N/A
uther Group Active 94e844b8-4031-7022-303d April 23 2025
John.Smith Group Pending e4c84458-30b1-7097-2496 N/A
luke Group Pending f4a89418-c0e1-705b-d050 N/A
Table 1 – CSV extract of total users report

This report displays Amazon Q Developer Pro user subscriptions, including subscription details, status, and last recorded account activity dates, which will be joined with usage metrics to generate customer insights.

Q Developer dashboard usage metrics

The Amazon Q Developer dashboard summarizes the data about how your Pro tier subscribers use the service. Amazon Q Developer generates and displays new metrics on an hourly basis for the most part. The only section that is not updated hourly is the Active user’s widget, which is updated daily according to the coordinated universal time (UTC) clock. The dashboard shows metrics collected from users who are subscribed in the AWS account that you’re currently signed into.

There are many metrics shown in the Q Developer dashboard usage metrics that help administrators monitor activity; detailed information and metrics are available on our documentation.

User Activity Reporting

The user activity reports in Amazon Q Developer provide metrics that detail how users interact with the service. To use them, you need to enable the feature and define an Amazon S3 bucket to save the CSV reports. Amazon Q Developer generates the report every day at midnight UTC and saves it into the designated bucket. Each row in the CSV file represents a user who interacted with Amazon Q Developer that day, and each column shows a metric as described in the User activity report metrics. These metrics are calculated based on the user telemetry collected over the course of the day. Instructions on how to enable and configure the User Activity Report Metrics can be found on our documentation.

Creating per-user level monthly report

To connect to the Amazon Q Developer Console, navigate to the AWS account from which you want to export your metrics. In the Amazon Q Developer Console, select “Settings” and then click on the “Edit” button for “Amazon Q Developer Usage Activity,” which is turned off by default.

Amazon Q Developer's usage activity panel. It displays the "Q Developer user activity report" setting is off.

Image 1 – Amazon Q Developer usage activity setting disabled

When prompted, enable the “Collect granular metrics per user” and define the s3://bucket/prefix. In my example, I pointed to the s3://q-dev-user-activity-<account-number>/csv

Amazon Q Developer's usage activity panel. It displays the "Q Developer user activity report" setting is on, and a populated S3 location field

Image 2 – Amazon Q Developer usage activity setting enabled

The csv files will be saved into the following directory

s3://bucketName/prefix/AWSLogs/accountId/QDeveloperLogs/by_user_analytic/region/year/month/day/utc-hour/

How to process the User Activity Report

I developed script that processes user activity data and subscription information stored in S3, combining them into monthly reports. The process_metrics.py script is a Python utility designed to process Amazon Q Developer user activity data and subscription information from AWS S3, combining them to generate monthly reports in CSV format. It retrieves data from S3 buckets, maps user IDs to names, aggregates metrics by user and month, and generates reports. The script leverages pandas for data manipulation. It generates a clean, structured CSV reports ready for your preferred analytics platform. The script logic derives the S3 directory structure, using current year, region and the AWS accountid, and all you need to inform is the bucket name and the prefix you initially configure for the CSV file. The script is shared below.


#!/usr/bin/env python3
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
"""
Amazon Q Metrics Processor

This script processes user activity data and subscription information from S3,
combines them, and generates monthly CSV reports.
"""

import os
import boto3
import botocore
from botocore.config import Config
import pandas as pd
import numpy as np
from datetime import datetime
import logging
from io import StringIO
import re
import argparse
from pathlib import Path  # from pathlib import Path
import sys
from urllib.parse import urlparse

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger('q-metrics')

def escape_log_data(data):
    """
    Sanitize data for secure logging to prevent log injection (CWE-117, CWE-93).
    
    Args:
        data: The data to be sanitized for logging
        
    Returns:
        str: Sanitized string safe for logging
    """
    if data is None:
        return 'None'
    
    # Convert to string if not already
    data_str = str(data)
    
    # Replace potentially dangerous characters
    # This prevents log forging by removing newlines and other control characters
    data_str = data_str.replace('\n', '\\n').replace('\r', '\\r')
    
    # Escape other control characters
    result = ''
    for char in data_str:
        if ord(char) < 32 or ord(char) == 127:  # Control characters
            result += f'\\x{ord(char):02x}'
        else:
            result += char
            
    return result

def validate_s3_bucket_name(bucket_name):
    """
    Validate S3 bucket name according to AWS naming rules.

    Args:
        bucket_name (str): The bucket name to validate

    Returns:
        bool: True if valid, False otherwise
    """
    if not bucket_name or not isinstance(bucket_name, str):
        return False

    # Check length (3-63 characters)
    if len(bucket_name)  63:
        return False

    # Check if it contains only allowed characters
    if not re.match(r'^[a-z0-9][a-z0-9\.-]*[a-z0-9]$', bucket_name):
        return False

    # Check if it doesn't contain consecutive periods
    if '..' in bucket_name:
        return False

    # Check if it's not an IP address
    if re.match(r'^\d+\.\d+\.\d+\.\d+$', bucket_name):
        return False

    # Check if it doesn't start with 'xn--' or end with '-s3alias'
    try:
        if bucket_name.startswith('xn--') or bucket_name.endswith('-s3alias'):
            return False
    except ValueError:
        return False

    return True

def validate_s3_path(path):
    """
    Validate an S3 path to ensure it doesn't contain dangerous characters.

    Args:
        path (str): The S3 path to validate

    Returns:
        bool: True if valid, False otherwise
    """
    if not path or not isinstance(path, str):
        return False

    # Check for path traversal attempts
    if '..' in path:
        return False

    # Check for invalid characters
    try:
        if re.search(r'[:"|?*\x00-\x1F]', path):
            return False
    except ValueError:
        return False

    return True

def validate_month_format(month_str):
    """
    Validate that a month string is in the format YYYY-MM.

    Args:
        month_str (str): The month string to validate

    Returns:
        bool: True if valid, False otherwise
    """
    if not month_str:
        return True  # Month is optional

    if not isinstance(month_str, str):
        return False

    # Check format YYYY-MM
    if not re.match(r'^[0-9]{4}-[0-9]{2}$', month_str):
        return False

    # Validate month range
    try:
        year, month = month_str.split('-')
        month_num = int(month)
        if month_num  12:
            return False
    except (ValueError, TypeError):
        return False

    return True

def sanitize_output_path(path):
    """
    Sanitize and normalize an output directory path.

    Args:
        path (str): The path to sanitize

    Returns:
        str: The sanitized absolute path
    """
    if not path or not isinstance(path, str):
        return os.path.abspath('./output')

    # Convert to Path object for safe handling
    safe_path = Path(path).resolve()

    # Ensure the path doesn't escape the intended directory structure
    try:
        # Make sure it's a valid path
        if not safe_path.is_absolute():
            safe_path = Path.cwd() / safe_path
    except (ValueError, TypeError):
        logger.warning("Invalid path: %s, using default", escape_log_data(repr(path)))
        return os.path.abspath('./output')

    return str(safe_path)

def validate_csv_content(df, expected_columns, file_type):
    """
    Validate that a DataFrame has the expected columns and structure.

    Args:
        df (DataFrame): The pandas DataFrame to validate
        expected_columns (list): List of required column names
        file_type (str): Type of file for logging purposes

    Returns:
        bool: True if valid, False otherwise
    """
    if df is None or df.empty:
        logger.error("Empty %s data", file_type)
        return False

    # Check for required columns
    missing_columns = [col for col in expected_columns if col not in df.columns]
    if missing_columns:
        logger.error("Missing required columns in %s data: %s", file_type, ', '.join(missing_columns))
        return False

    # Check for empty required columns
    for col in expected_columns:
        if df[col].isna().all():
            logger.error("Column '%s' in %s data is completely empty", col, file_type)
            return False

    # Check for reasonable row count
    if len(df) == 0:
        logger.error("No data rows in %s data", file_type)
        return False

    # Check for duplicate rows
    if df.duplicated().any():
        dup_count = df.duplicated().sum()
        logger.warning("Found %d duplicate rows in %s data", dup_count, file_type)

    return True

def validate_subscription_data(df):
    """
    Validate subscription data format and content.

    Args:
        df (DataFrame): The subscription data DataFrame

    Returns:
        bool: True if valid, False otherwise
    """
    required_columns = [
        'Name',
        'Subscription type',
        'Subscription status',
        'Identity provider user ID'
    ]

    return validate_csv_content(df, required_columns, "subscription")

def validate_activity_data(df):
    """
    Validate activity data format and content.

    Args:
        df (DataFrame): The activity data DataFrame

    Returns:
        bool: True if valid, False otherwise
    """
    required_columns = ['UserId', 'Date']

    # Basic validation
    if not validate_csv_content(df, required_columns, "activity"):
        return False

    # Check for at least one metric column
    metric_cols = df.select_dtypes(include=[np.number]).columns
    if len(metric_cols) == 0:
        logger.error("No metric columns found in activity data")
        return False

    # Check for valid date format
    try:
        valid_dates = 0
        total_dates = len(df['Date'])

        for date_str in df['Date']:
            if parse_date(date_str) is not None:
                valid_dates += 1

        if valid_dates == 0:
            logger.error("No valid dates found in activity data")
            return False
        elif valid_dates < total_dates:
            logger.warning("Only %d out of %d dates are valid in activity data", valid_dates, total_dates)
    except Exception as e:
        logger.error("Error validating dates in activity data: %s", str(e))
        return False

    return True



def parse_args():
    """Parse command line arguments with enhanced security validation."""
    parser = argparse.ArgumentParser(description='Process Amazon Q metrics data')
    parser.add_argument('--bucket', required=True, help='S3 bucket name')
    parser.add_argument('--prefix', required=True, help='Initial S3 prefix (e.g., "logs")')
    parser.add_argument('--subscription-path', required=True,
                        help='S3 path to subscription file (e.g., user-activities/subscriptions.csv)')
    parser.add_argument('--output-dir', default='./output', help='Local directory for output files')
    parser.add_argument('--month', help='Process only a specific month (format: YYYY-MM, e.g., 2025-01)')
    parser.add_argument('--per-user', action='store_true', help='Generate individual reports for each user')
    parser.add_argument('--user', help='Generate report for a specific user (by name)')

    args = parser.parse_args()

    # Validate bucket name with enhanced checks
    if not validate_s3_bucket_name(args.bucket):
        logger.error("Invalid S3 bucket name: %r", escape_log_data(args.bucket))
        sys.exit(1)
    
    # Additional bucket name security check - prevent command injection via bucket names
    if re.search(r'[;&|`$]', args.bucket):
        logger.error("Potentially malicious characters in bucket name: %r", escape_log_data(args.bucket))
        sys.exit(1)

    # Derive activity-prefix from the provided prefix
    try:
        # Get AWS account ID
        sts_client = boto3.client('sts')
        account_id = sts_client.get_caller_identity()['Account']
        
        # Get current region
        session = boto3.session.Session()
        region = session.region_name or os.environ.get('AWS_REGION', 'us-east-1')
        
        # Check if region is supported
        supported_regions = ['us-east-1', 'eu-central-1']
        if region not in supported_regions:
            logger.error("Region %s is not supported. This solution currently only works in %s", 
                        escape_log_data(region), ' or '.join(supported_regions))
            sys.exit(1)
        
        # Get current year
        current_year = str(datetime.now().year)
        
        # If month is provided, extract year from it
        if args.month:
            try:
                year, _ = args.month.split('-')
                current_year = year
            except (ValueError, TypeError):
                pass
                
        # Construct the activity prefix using the provided prefix
        activity_prefix = f"{args.prefix}/AWSLogs/{account_id}/QDeveloperLogs/by_user_analytic/{region}/{current_year}"
        logger.info("Derived activity prefix: %s", escape_log_data(activity_prefix))
    except Exception as e:
        logger.error("Failed to derive activity prefix: %s", escape_log_data(str(e)))
        sys.exit(1)
    
    # Validate S3 paths with enhanced checks
    for path_arg, path_name in [(activity_prefix, "activity prefix"), 
                               (args.subscription_path, "subscription path")]:
        if not validate_s3_path(path_arg):
            logger.error("Invalid S3 %s: %r", path_name, escape_log_data(path_arg))
            sys.exit(1)
        
        # Additional path security checks
        if re.search(r'[;&|`$]', path_arg):
            logger.error("Potentially malicious characters in %s: %r", path_name, escape_log_data(path_arg))
            sys.exit(1)
        
        # Check for path traversal attempts with more patterns
        if any(pattern in path_arg for pattern in ['../', '..\\', '../', '..\\']):
            logger.error("Path traversal attempt detected in %s: %r", path_name, escape_log_data(path_arg))
            sys.exit(1)

    # Validate month format if provided with enhanced checks
    if args.month:
        if not validate_month_format(args.month):
            logger.error("Invalid month format: %r. Expected format: YYYY-MM (e.g., 2025-01)", escape_log_data(args.month))
            sys.exit(1)
        
        # Additional validation for month - check for reasonable date range
        try:
            year, month = args.month.split('-')
            year_num = int(year)
            month_num = int(month)
            
            current_year = datetime.now().year
            
            # Check for reasonable year range (past 5 years to next year)
            if year_num  current_year + 1:
                logger.warning("Month year %d is outside the reasonable range (%d-%d)", 
                              year_num, current_year - 5, current_year + 1)
        except (ValueError, TypeError):
            # Already validated by validate_month_format, this is just an extra check
            pass

    # Validate user argument if provided
    if args.user:
        # Check for reasonable length
        if len(args.user) > 100:
            logger.error("User name too long: %d characters (max 100)", len(args.user))
            sys.exit(1)
        
        # Check for potentially dangerous characters
        if re.search(r'[;&|`$]', args.user):
            logger.error("Potentially malicious characters in user name: %r", escape_log_data(args.user))
            sys.exit(1)

    # Sanitize output directory with enhanced security
    args.output_dir = sanitize_output_path(args.output_dir)
    
    # Additional output directory security check
    try:
        output_path = Path(args.output_dir)
        
        # Check if the path exists and is a directory
        if output_path.exists() and not output_path.is_dir():
            logger.error("Output path exists but is not a directory: %r", escape_log_data(args.output_dir))
            sys.exit(1)
            
        # Check if we have write permissions to the directory or its parent
        parent_dir = output_path if output_path.exists() else output_path.parent
        if not os.access(parent_dir, os.W_OK):
            logger.error("No write permission for output directory: %r", escape_log_data(args.output_dir))
            sys.exit(1)
    except Exception as e:
        logger.error("Error validating output directory: %s", escape_log_data(str(e)))
        sys.exit(1)
        
    logger.info("Using output directory: %r", escape_log_data(args.output_dir))
    
    # Add the derived activity_prefix to args for use in the rest of the program
    args.activity_prefix = activity_prefix

    return args

def get_s3_client():
    """Create and return an S3 client with proper configuration."""
    try:
        # Configure S3 client with timeouts and retries
        config = Config(
            connect_timeout=5,  # 5 seconds connection timeout
            read_timeout=30,    # 30 seconds read timeout
            retries={'max_attempts': 3},  # Retry configuration
            signature_version='s3v4'  # Use more secure signature version
        )
        
        # Create the client with the custom configuration
        s3 = boto3.client('s3', config=config)
        
        # Test the client with a simple operation to validate credentials
        try:
            # Use head_bucket which is a lightweight operation
            s3.head_bucket(Bucket='aws-sdk-resources')
        except botocore.exceptions.ClientError as e:
            error_code = e.response.get('Error', {}).get('Code', '')
            if error_code == '403':
                logger.warning("AWS credentials appear valid but have insufficient permissions")
            elif error_code == '401':
                logger.error("Invalid AWS credentials")
                sys.exit(1)
        except Exception as e:
            logger.warning("Error testing S3 client: %s", str(e))
        
        return s3
    except Exception as e:
        logger.error("Failed to create S3 client: %s", str(e))
        sys.exit(1)

def list_activity_files(s3_client, bucket, prefix, month=None):
    """List all activity files in the specified S3 bucket and prefix.

    If month is specified, only return files for that month (format: YYYY-MM).

    Args:
        s3_client: The boto3 S3 client
        bucket (str): The S3 bucket name
        prefix (str): The S3 prefix for activity files
        month (str, optional): Month in YYYY-MM format

    Returns:
        list: List of S3 keys for activity files
    """
    # Validate inputs again for safety
    if not validate_s3_bucket_name(bucket):
        logger.error("Invalid bucket name: %r", escape_log_data(bucket))
        return []

    if not validate_s3_path(prefix):
        logger.error("Invalid S3 prefix: %r", escape_log_data(prefix))
        return []

    if month and not validate_month_format(month):
        logger.error("Invalid month format: %r", escape_log_data(month))
        return []

    # Sanitize prefix to ensure it doesn't have path traversal
    prefix = prefix.replace('..', '').replace('//', '/')

    logger.info("Listing activity files in s3://%s/%s", escape_log_data(bucket), escape_log_data(prefix))

    activity_files = []
    paginator = s3_client.get_paginator('list_objects_v2')

    try:
        # If month is specified, filter by the month prefix
        search_prefix = prefix
        if month:
            try:
                year, month_num = month.split('-')
                # Make sure we're not duplicating the year in the path
                if not prefix.endswith(year + '/'):
                    search_prefix = f"{prefix}{month_num}/"
                else:
                    search_prefix = f"{prefix}{month_num}/"
                logger.info("Filtering for month %s using prefix: %s", escape_log_data(month), escape_log_data(search_prefix))
            except ValueError:
                logger.error("Failed to parse month %r for filtering", escape_log_data(month))
                return []

        for page in paginator.paginate(Bucket=bucket, Prefix=search_prefix):
            if 'Contents' in page:
                for obj in page['Contents']:
                    key = obj['Key']
                    # Skip directories or non-CSV files
                    if not key.endswith('/') and key.endswith('.csv'):
                        activity_files.append(key)

        logger.info("Found %d activity files", len(activity_files))
        return activity_files
    except Exception as e:
        logger.error("Error listing activity files: %s", escape_log_data(str(e)))
        if isinstance(e, client('s3').exceptions.NoSuchBucket):
            logger.error("Bucket %r does not exist", escape_log_data(bucket))
        elif isinstance(e, client('s3').exceptions.AccessDenied):
            logger.error("Access denied to bucket %r", escape_log_data(bucket))
        return []

def read_csv_from_s3(s3_client, bucket, key):
    """Read a CSV file from S3 into a pandas DataFrame.

    Args:
        s3_client: The boto3 S3 client
        bucket (str): The S3 bucket name
        key (str): The S3 object key

    Returns:
        DataFrame or None: Pandas DataFrame with CSV content or None if error
    """
    # Validate inputs
    if not validate_s3_bucket_name(bucket):
        logger.error("Invalid bucket name: %r", escape_log_data(bucket))
        return None

    if not validate_s3_path(key):
        logger.error("Invalid S3 key: %r", escape_log_data(key))
        return None

    logger.info("Reading s3://%s/%s", escape_log_data(bucket), escape_log_data(key))

    try:
        # Get object metadata first to check file size
        try:
            head_response = s3_client.head_object(Bucket=bucket, Key=key)
            file_size_bytes = head_response.get('ContentLength', 0)
            
            # Set a reasonable size limit (e.g., 100MB)
            MAX_FILE_SIZE_BYTES = 100 * 1024 * 1024  # 100MB
            
            if file_size_bytes > MAX_FILE_SIZE_BYTES:
                logger.error("File %r size (%d bytes) exceeds the maximum allowed size (%d bytes)", 
                             escape_log_data(key), file_size_bytes, MAX_FILE_SIZE_BYTES)
                return None
        except Exception as e:
            logger.warning("Could not check file size for %r: %s", escape_log_data(key), escape_log_data(str(e)))
            # Continue anyway, we'll have other checks later

        response = s3_client.get_object(Bucket=bucket, Key=key)
        content = response['Body'].read().decode('utf-8')

        # Check for CSV injection attempts
        if any(suspicious_pattern in content for suspicious_pattern in ['=cmd|', '=cmd:', '@cmd', '+cmd', '-cmd', '=DDE', '=SUM(', '=HYPERLINK(']):
            logger.error("Potential CSV injection detected in %r", escape_log_data(key))
            return None

        # Use a StringIO buffer to safely parse the CSV
        csv_buffer = StringIO(content)

        # Read with error handling for malformed CSV
        try:
            # First check number of rows by reading just the header
            row_count = sum(1 for _ in csv_buffer) - 1  # Subtract 1 for header
            csv_buffer.seek(0)  # Reset buffer position
            
            # Set a hard limit on number of rows
            MAX_ROWS = 500000  # Hard limit of 500K rows
            
            if row_count > MAX_ROWS:
                logger.error("CSV file %r has %d rows, which exceeds the maximum limit of %d rows", 
                             escape_log_data(key), row_count, MAX_ROWS)
                return None
                
            # Use converters to sanitize string inputs
            df = pd.read_csv(csv_buffer, converters={col: str for col in ['Name', 'UserId', 'Subscription', 'Subscription type', 'Subscription status']})

            # Check memory usage of the DataFrame
            memory_usage_bytes = df.memory_usage(deep=True).sum()
            MAX_MEMORY_USAGE = 500 * 1024 * 1024  # 500MB limit
            
            if memory_usage_bytes > MAX_MEMORY_USAGE:
                logger.error("DataFrame for %r uses %d bytes of memory, exceeding the limit of %d bytes", 
                             escape_log_data(key), memory_usage_bytes, MAX_MEMORY_USAGE)
                del df  # Explicitly delete to free memory
                return None

            # Check for reasonable file size (soft warning)
            if len(df) > 100000:  # Lower the warning threshold to 100K rows
                logger.warning("CSV file %r has %d rows, which exceeds the recommended limit", escape_log_data(key), len(df))

            return df
        except pd.errors.ParserError as e:
            logger.error("Error parsing CSV %r: %s", escape_log_data(key), escape_log_data(str(e)))
            return None

    except Exception as e:
        logger.error("Error reading %r: %s", escape_log_data(key), escape_log_data(str(e)))
        return None

def parse_date(date_str):
    """Parse date strings into datetime objects."""
    if pd.isna(date_str) or date_str == 'N/A':
        return None

    # Handle different date formats
    date_formats = [
        '%m-%d-%Y',  # 02-03-2025
        '%B %d %Y',  # March 13 2025
    ]

    for fmt in date_formats:
        try:
            return datetime.strptime(date_str, fmt)
        except ValueError:
            continue

    logger.warning("Could not parse date: %r", escape_log_data(date_str))
    return None

def extract_month_year(date_obj):
    """Extract month and year from a datetime object."""
    if date_obj is None:
        return None
    try:
        return f"{date_obj.year}-{int(date_obj.month):02d}"
    except (AttributeError, ValueError, TypeError) as e:
        logger.debug("Failed to extract month/year from date object: %s", escape_log_data(str(e)))
        return None

def process_subscription_data(df):
    """Process subscription data."""
    logger.info("Processing subscription data")

    # Validate subscription data
    if not validate_subscription_data(df):
        logger.error("Invalid subscription data format")
        return None, {}

    # Clean up subscription data
    df_clean = df.copy()
    
    # Add 'Subscription' column if it doesn't exist (using Subscription type as default)
    if 'Subscription' not in df_clean.columns:
        df_clean['Subscription'] = df_clean['Subscription type']
        logger.info("Added 'Subscription' column based on 'Subscription type'")

    # Map user IDs to names
    id_to_name_map = dict(zip(df_clean['Identity provider user ID'], df_clean['Name']))

    # Parse last activity date
    df_clean['Last activity date'] = df_clean['Last activity date'].apply(parse_date)
    df_clean['Last activity month'] = df_clean['Last activity date'].apply(extract_month_year)

    return df_clean, id_to_name_map

def process_activity_data(activity_dfs, id_to_name_map):
    """Process and combine activity data."""
    logger.info("Processing activity data")

    if not activity_dfs:
        logger.warning("No activity data to process")
        return pd.DataFrame()

    # Validate each activity dataframe
    valid_dfs = []
    for i, df in enumerate(activity_dfs):
        if validate_activity_data(df):
            valid_dfs.append(df)
        else:
            logger.warning("Skipping invalid activity data file #%d", i+1)

    if not valid_dfs:
        logger.error("No valid activity data files found")
        return pd.DataFrame()

    try:
        # Combine all activity dataframes
        combined_df = pd.concat(valid_dfs, ignore_index=True)

        # Parse dates and extract month-year
        combined_df['Date'] = combined_df['Date'].apply(parse_date)
        combined_df['Month'] = combined_df['Date'].apply(extract_month_year)

        # Add user names based on ID mapping
        combined_df['Name'] = combined_df['UserId'].map(id_to_name_map)
        
        # Check if any user IDs couldn't be mapped to names
        unmapped_ids = combined_df[combined_df['Name'].isna()]['UserId'].unique()
        if len(unmapped_ids) > 0:
            logger.warning("Found %d user IDs without matching names", len(unmapped_ids))
            if len(unmapped_ids)  MAX_REPORTS:
        logger.warning("Too many months (%d). Limiting to %d most recent months.", 
                      len(months), MAX_REPORTS)
        # Sort months and take the most recent ones
        months = sorted(months, reverse=True)[:MAX_REPORTS]

    reports_generated = 0
    for month in months:
        if pd.isna(month):
            logger.debug("Skipping null month value")
            continue

        # Skip if specific_month is provided and doesn't match current month
        if specific_month and month != specific_month:
            continue

        # Validate month format
        if not validate_month_format(month):
            logger.warning("Skipping invalid month format: %r", escape_log_data(month))
            continue

        try:
            month_df = agg_df[agg_df['Month'] == month]

            # Create a safe filename
            safe_month = re.sub(r'[^\w\-]', '_', month)
            
            # Additional security check for filename
            if not safe_month or safe_month.startswith('.'):
                logger.warning("Invalid month format after sanitization: %r", escape_log_data(safe_month))
                continue
                
            output_file = os.path.join(output_dir, f"q-metrics-{safe_month}.csv")
            
            # Verify the output path is still within the intended directory
            output_path = Path(output_file).resolve()
            if not str(output_path).startswith(str(Path(output_dir).resolve())):
                logger.error("Path traversal attempt detected in output file: %r", escape_log_data(output_file))
                continue

            # Check if the dataframe is empty
            if month_df.empty:
                logger.warning("No data for month %r, skipping report generation", escape_log_data(month))
                continue
                
            # Limit the size of the output file
            if len(month_df) > 100000:
                logger.warning("Month %r has too many rows (%d). Truncating to 100,000 rows.", 
                              escape_log_data(month), len(month_df))
                month_df = month_df.head(100000)

            # Write with secure file handling
            temp_file = output_file + '.tmp'
            month_df.to_csv(temp_file, index=False)
            
            # Use atomic rename for safer file writing
            os.replace(temp_file, output_file)
            
            # Set secure permissions
            os.chmod(output_file, 0o640)  # rw-r-----
            
            logger.info("Generated report for %s: %s", escape_log_data(month), escape_log_data(output_file))
            reports_generated += 1
        except (PermissionError, OSError) as e:
            logger.error("Error writing to %r: %s", escape_log_data(output_file), escape_log_data(str(e)))
        except Exception as e:
            logger.error("Error generating report for month %r: %s", escape_log_data(month), escape_log_data(str(e)))

    return reports_generated

def generate_user_reports(agg_df, output_dir, specific_user=None):
    """Generate per-user CSV reports.

    If specific_user is provided, only generate a report for that user.

    Args:
        agg_df (DataFrame): Aggregated data frame
        output_dir (str): Output directory path
        specific_user (str, optional): Specific user name

    Returns:
        int: Number of reports generated
    """
    logger.info("Generating per-user reports")

    # Validate output directory
    output_dir = sanitize_output_path(output_dir)

    # Create output directory for user reports
    user_dir = os.path.join(output_dir, "users")
    try:
        os.makedirs(user_dir, exist_ok=True)
    except (PermissionError, OSError) as e:
        logger.error("Cannot create user directory %s: %s", escape_log_data(user_dir), escape_log_data(str(e)))
        return 0

    # Check if dataframe is empty
    if agg_df.empty:
        logger.warning("No data available to generate user reports")
        return 0

    # Check if Name column exists
    if 'Name' not in agg_df.columns:
        logger.error("Required column 'Name' not found in data")
        return 0

    # Get list of users
    users = agg_df['Name'].unique()
    if len(users) == 0:
        logger.warning("No user data available in the aggregated dataframe")
        return 0

    reports_generated = 0
    for user in users:
        if pd.isna(user):
            logger.debug("Skipping null user value")
            continue

        # Skip if specific_user is provided and doesn't match current user
        if specific_user and user != specific_user:
            continue

        try:
            user_df = agg_df[agg_df['Name'] == user]
            
            # Check if the dataframe is empty
            if user_df.empty:
                logger.warning("No data for user %r, skipping report generation", escape_log_data(user))
                continue

            # Create a safe filename from the user name using a more secure approach
            # Only allow alphanumeric characters, underscores, and hyphens
            safe_name = re.sub(r'[^\w\-]', '_', str(user))

            # Prevent directory traversal by removing any path components
            safe_name = os.path.basename(safe_name)

            # Ensure the filename is not empty and doesn't start with a dot
            if not safe_name or safe_name.startswith('.'):
                safe_name = f"user_{hash(user) % 10000}"

            output_file = os.path.join(user_dir, f"q-metrics-{safe_name}.csv")

            user_df.to_csv(output_file, index=False)
            logger.info("Generated report for user %r: %s", escape_log_data(user), escape_log_data(output_file))
            reports_generated += 1
        except (PermissionError, OSError) as e:
            logger.error("Error writing to %s: %s", escape_log_data(output_file), escape_log_data(str(e)))
        except Exception as e:
            logger.error("Error generating report for user %r: %s", escape_log_data(user), escape_log_data(str(e)))

    return reports_generated

def main():
    """Main function to process metrics data with enhanced security."""
    try:
        # Memory limit has been removed as requested
        
        # Parse and validate arguments
        args = parse_args()

        # Initialize S3 client with secure configuration
        s3_client = get_s3_client()

        # Set timeout for operations
        import signal
        
        def timeout_handler(signum, frame):
            logger.error("Operation timed out")
            sys.exit(1)
        
        # Set a global timeout of 10 minutes for the entire process
        signal.signal(signal.SIGALRM, timeout_handler)
        signal.alarm(600)  # 600 seconds = 10 minutes

        # Read subscription data with integrity verification
        subscription_df = read_csv_from_s3(s3_client, args.bucket, args.subscription_path)
        if subscription_df is None:
            logger.error("Failed to read subscription data. Exiting.")
            return 1

        # Process subscription data
        subscription_df, id_to_name_map = process_subscription_data(subscription_df)
        if subscription_df is None:
            logger.error("Failed to process subscription data. Exiting.")
            return 1

        # List and read activity files
        activity_files = list_activity_files(s3_client, args.bucket, args.activity_prefix, args.month)
        if not activity_files:
            logger.warning("No activity files found. Proceeding with empty activity data.")
        
        # Limit the number of files processed to prevent resource exhaustion
        MAX_FILES = 100
        if len(activity_files) > MAX_FILES:
            logger.warning("Too many activity files found (%d). Limiting to %d files.", 
                          len(activity_files), MAX_FILES)
            activity_files = activity_files[:MAX_FILES]
        
        activity_dfs = []
        for file_key in activity_files:
            # Check for timeout or interruption between file processing
            if hasattr(signal, 'SIGINFO'):  # macOS specific
                signal.signal(signal.SIGINFO, lambda signum, frame: logger.info("Processing file: %s", file_key))
                
            df = read_csv_from_s3(s3_client, args.bucket, file_key)
            if df is not None:
                activity_dfs.append(df)
            else:
                logger.warning("Skipping invalid activity file: %r", file_key)

        # Process activity data
        activity_df = process_activity_data(activity_dfs, id_to_name_map)
        if activity_df.empty and activity_files:
            logger.warning("No valid activity data could be processed from %d files", len(activity_files))

        # Merge data
        merged_df = merge_data(activity_df, subscription_df)

        # Aggregate by month
        agg_df = aggregate_by_month(merged_df)
        if agg_df.empty:
            logger.warning("No data available after aggregation. Reports will be empty.")

        # Generate monthly reports
        num_reports = generate_monthly_reports(agg_df, args.output_dir, args.month)
        logger.info("Successfully generated %d monthly reports", num_reports)

        # Generate per-user reports if requested
        if args.per_user or args.user:
            num_user_reports = generate_user_reports(agg_df, args.output_dir, args.user)
            logger.info("Successfully generated %d user reports", num_user_reports)
            
        # Cancel the alarm since we're done
        signal.alarm(0)
        
        return 0

    except Exception as e:
        # Limit error disclosure in logs
        logger.error("Error processing metrics: %s", escape_log_data(str(e)))
        # Only log full traceback in debug mode
        if logger.level <= logging.DEBUG:
            logger.debug("Detailed error information:", exc_info=True)
        return 1
    finally:
        # Ensure we cancel any pending alarms
        if 'signal' in locals():
            try:
                signal.alarm(0)
            except:
                pass

if __name__ == "__main__":
    exit(main())

This is an example of how you can invoke it:

python3 process_metrics.py --bucket my-metrics-bucket \
                          --prefix logs \
                          --subscription-path user-activities/subscriptions.csv \
                          --output-dir ./reports \
                          --month 2025-01 \
                          --per-user

This command will:

  • Read subscription data from

s3://my-metrics-bucket/user-activities/subscriptions.csv

  • Look for activity logs in

s3://my-metrics-bucket/logs/AWSLogs/{account-id}/QDeveloperLogs/by_user_analytic/{region}/2025/01/

  • Process only data from January 2025 (due to the –month 2025-01 parameter)
  • Generate both monthly summary reports and individual user reports (due to –per-user)
  • Save all reports to the ./reports directory

In this new era of prompts, I will also share the prompt used as the foundation for the script that processes user activity data and subscription information stored in S3, combining them into monthly reports. Note that the original prompt was simpler. I utilized Q Developer to enhance the prompt based on my initial request. The final code integrates elements from the initial prompt and my modifications. The initial prompt likely contributed to 80-90% of the final script.

Create a Python script that processes Amazon Q Developer metrics data from S3. 

1. Input Sources:
    - User Activity Data:
        - Location: s3://YOURBUCKET/USER_DATA_KEY
        - Structure: CSV files organized in month/day folders
        - Key field: UserId
        - Date field: format MM-DD-YYYY
    - User Subscription Data:
        - Location: s3://YOURBUCKET/Amazon_Q_Users_Subscription_List.csv
        - Key field: Identity provider user ID (maps to UserId in activity data)
2. Processing Requirements:
    - Read all CSV files from the activity data folder structure
    - Join with subscription data using UserId/'Identity provider user ID'
    - Aggregate data by user and month using the Date field
    - Calculate monthly totals for all metrics
    - Include security features like input validation and sanitization
    - Replace NaN with 0
    - Some columns does not exists in all csv files
    - Use boto3 to interact with AWS S3
    - Use pandas for data processing
    - Include proper error handling and logging
    - Validate all inputs to prevent security issues
3. Script Requirements:
    - The script should be well-structured with separate functions
    - Argument parsing and validation
    - S3 client initialization
    - File listing and reading from S3
    - Data processing and aggregation
    - Report generation
4. Support command-line arguments for:
   - S3 bucket name
   - S3 prefix for logs
   - Path to subscription file
   - Output directory for reports
   - Optional filtering by month (YYYY-MM format)
   - Optional per-user report generation
   - Optional filtering for a specific user

Output example

Table 2 presents an extract of the script’s output, consolidating user interactions during March 2025. The data reveals interesting usage patterns among team members. While Artur shows a strong preference for chat and inline-chat interactions, Uther tends to engage more frequently with the /dev agent. This contrast in usage styles presents an opportunity for knowledge sharing within the team. I plan to ask Artur to demonstrate his workflow and possibly create a tutorial video showcasing how he creatively and effectively uses Q Developer in his daily work. This could inspire Uther and other team members to explore different interaction methods and potentially enhance their productivity through increased chat engagement.

Name Month Chat_MessagesSent InlineChat_AcceptedLineAdditions Dev_GeneratedLines
artur Mar-25 475 206 109
uther Mar-25 70 8 218
Table 2 – CSV extract of the script output

Conclusion

By combining subscription management, the developer dashboard, and user activity reporting, organizations can achieve a holistic understanding of their developers’ usage patterns. With this approach we can answer the initial questions posed at the beginning of this blog. Here’s how these features work together:

  1. How many Q Developer active users are there?

Answer: As a management account administrator within an organization, enable trusted access to view Amazon Q Developer subscriptions and their status from both management and member accounts in a unified list. For a single Amazon Q Developer AWS Account, the subscription displays all related subscriptions.

  1. How can we track usage trends?

Answer: The Amazon Q Developer Dashboard delivers insights into Amazon Q Developer feature usage, helping administrators pinpoint where developers gain the most value as an organization.

  1. Who are our power users?

Answer: The User Activity Reporting provides detailed metrics on user interactions, allowing administrators to identify top users, patterns, and potential enablement sessions for those who haven’t fully explored Amazon Q Developer.

Artur Rodrigues

Artur Rodrigues is a Principal Solutions Architect for Generative AI at Amazon Web Services (AWS), focused on the Next Generation Developer experience, enabling developers to work more efficiently and creatively through the integration of Generative AI into their workflows. Artur enjoys cycling and exploring the great outdoors of beautiful British Columbia in Canada. He is also a gelato aficionado and a fan of soccer and jiu-jitsu.

Friday Squid Blogging: US Naval Ship Attacked by Squid in 1978

Post Syndicated from Bruce Schneier original https://www.schneier.com/blog/archives/2025/05/friday-squid-blogging-us-naval-ship-attacked-by-squid-in-1978.html

Interesting story:

USS Stein was underway when her anti-submarine sonar gear suddenly stopped working. On returning to port and putting the ship in a drydock, engineers observed many deep scratches in the sonar dome’s rubber “NOFOUL” coating. In some areas, the coating was described as being shredded, with rips up to four feet long. Large claws were left embedded at the bottom of most of the scratches.

As usual, you can also use this squid post to talk about the security stories in the news that I haven’t covered.

[$] Reports from OSPM 2025, day two

Post Syndicated from corbet original https://lwn.net/Articles/1021332/

The seventh edition of the Power Management and Scheduling
in the Linux Kernel Summit
(known as “OSPM”) took place on March 18-20,
2025. Topics discussed on the second day include improvements to device
suspend and resume, the status and future of sched_ext, the scx_lavd
scheduler, improving the efficiency of load balancing, and hierarchical
constant bandwidth server scheduling.

[$] Formally verifying the BPF verifier

Post Syndicated from daroc original https://lwn.net/Articles/1020664/

The BPF verifier is an increasingly complex and security-critical piece of code.
When the kinds of people who are apt to work on BPF see a situation like that,
they naturally question whether it’s possible to use formal verification to
ensure that the implementation of the code in question is correct. Santosh
Nagarakatte led the first of two extra-long sessions in the BPF track
of the 2025 Linux Storage, Filesystem, Memory Management, and BPF Summit
about his team’s work formally verifying the BPF verifier with a
custom tool called

Agni
.

Qualcomm Discrete NPU Spotted at in Dell Pro Max Plus laptop at DTW

Post Syndicated from Will Taillac original https://www.servethehome.com/qualcomm-discrete-qualcomm-npu-spotted-at-in-dell-pro-max-plus-laptop-at-dtw/

At Dell Tech World 2025, the company showed off a new laptop class that had Qualcomm NPUs instead of a dGPU for heavier AI workloads

The post Qualcomm Discrete NPU Spotted at in Dell Pro Max Plus laptop at DTW appeared first on ServeTheHome.

OpenSearch UI: Six months in review

Post Syndicated from Muthu Pitchaimani original https://aws.amazon.com/blogs/big-data/opensearch-ui-six-months-in-review/

OpenSearch UI has been adopted by thousands of customers for various use cases since its launch in November 2024. Exciting customer stories and feedback have helped shape our feature improvements. As we complete 6 months since its general availability, we are sharing major enhancements that have improved OpenSearch UI’s capability, especially in observability and security analytics, in this post.

OpenSearch UI is a serverless, fully managed dashboard to provide a scalable, zero-downtime, web-based interface for data analytics and visualizations. With OpenSearch UI, you can have a unified interface to gain actionable insights across multiple data sources, including Amazon OpenSearch Service domains, Amazon OpenSearch Serverless collections, and AWS services such as Amazon CloudWatch and Amazon Security Lake.

Use natural language for your AI-powered analytics with Amazon Q Developer

OpenSearch UI has transformed complex data analysis to be as simple as asking questions in natural language with its integration with Amazon Q Developer in OpenSearch. You can access the conversational chat pane by choosing the Amazon Q Developer icon in the top right corner of the UI. Amazon Q Developer will answer generic questions such as how to use the features in OpenSearch UI and how to use OpenSearch UI with additional data sources.

You can use the search bar on the Discover page to use the generative AI capabilities with your OpenSearch data. You can enter your question about your data in natural language. The query assistant feature will translate your question to Piped Processing Language (PPL), run the query, and show the results. There will also be an Amazon Q Summary section generated from the query results to answer your question. The query assistant feature now also works with data connections from Amazon Simple Storage Service (Amazon S3).

Additionally, you can use the generative AI feature for anomaly detection and visualizations for your data, so it’s straightforward to identify potential issues earlier and faster, reducing the mean time to resolution.

When an alert is triggered, you can choose the Amazon Q icon to generate a summary of the alert, so you can catch up on the context of this alert. The View insights button will provide further analysis of the alerts in combination with OpenSearch knowledge through a process called Retrieval Augmented Generation (RAG). If you want to further investigate the alert, you can choose View in Discover to proceed to log analytics.

Amazon Q Developer in OpenSearch Service will help you reduce troubleshooting time, resolve more issues without escalation, and extract actionable insights from your operational data using natural language instead of specialized queries. Refer to Amazon Q Developer in Amazon OpenSearch Service to get started with the AI assisted analytics experience.

Enhance enterprise security

We have improved OpenSearch UI’s security capability to meet the demanding needs of large enterprises. Through these enhancements, we’re making it seamless to manage secure access at scale so you can have precise control over who can access your analytics workspaces and data that resides in them.

Use SAML workflows through IAM federation

OpenSearch UI now supports Security Assertion Markup Language (SAML) through AWS Identity and Access Management (IAM) federation so that you can create a single sign-on (SSO) experience for your end-users that initiates authentication workflows from your external identity providers (IdPs), typically called IdP-initiated SSO. You might find this process familiar if your organization is using external IdPs (such as Okta) to manage user permissions and track user activities in accessing AWS services. You can now define a default relay state URL to share with your end-users with this support. Your end-users can use this URL to land directly in OpenSearch UI after authenticating with their IdP. You can also achieve fine-grained access control by defining different permissions for each IAM role assumed by different end-users. To get started, refer to Enabling SAML federation with AWS Identity and Access Management.

Secure access with AWS PrivateLink

OpenSearch UI now supports AWS PrivateLink. You can now access OpenSearch UI privately from within your virtual private cloud (VPC). To learn more, see Managing access to the OpenSearch UI from a VPC endpoint.

Enhancing workspace privacy

There are also new workspace-level privacy settings, so you can quickly configure your workspace with the right permissions with collaborators. For more details, refer to Using Amazon OpenSearch Service workspaces.

Expanded data access capabilities

OpenSearch UI now also offers following additional data access capabilities.

Support for cross-cluster search

Cross-cluster search is an OpenSearch feature with which you can query multiple connected OpenSearch Service domains across accounts and across AWS Regions. We added the capability to support these connected domains as data sources in OpenSearch UI. With this support, you can view remote connected clusters with an index pattern under the data source for the source cluster. To learn more, see Cross-Region and cross-account data access with cross-cluster search.

Regional expansion

To further expand the data access capabilities of OpenSearch UI, we expanded its availability to two more regions: Asia Pacific (Hong Kong) and Europe (Stockholm).

Conclusion

The past 6 months after general availability of OpenSearch UI have seen significant progress in making OpenSearch UI more user-friendly, more available, and more secure. From natural language-based exploration to enterprise security, these feature enhancements reflect our commitment to simplify and improve your data analytics experience. To learn more, refer to Using OpenSearch UI in Amazon OpenSearch Service and get updates through Amazon OpenSearch Service user interface release history.


About the Authors

Muthu Pitchaimani is a Search Specialist with Amazon OpenSearch Service. He builds large-scale search applications and solutions. Muthu is interested in the topics of networking and security, and is based out of Austin, Texas.

Hang (Arthur) Zuo is a Senior Product Manager with Amazon OpenSearch Service. Arthur leads generative AI, workspaces, and infrastructural features in OpenSearch UI. Arthur is passionate about cloud technologies and building data products that help users and businesses gain actionable insights and achieve operational excellence.

Cloudflare named in 2025 Gartner® Magic Quadrant™ for Security Service Edge

Post Syndicated from Abe Carryl original https://blog.cloudflare.com/cloudflare-sse-gartner-magic-quadrant-2025/

For the third consecutive year, Gartner has named Cloudflare in the Gartner® Magic Quadrant™ for Security Service Edge (SSE) report. This analyst evaluation helps security and network leaders make informed choices about their long-term partners in digital transformation. We are excited to share that Cloudflare is one of only nine vendors recognized in this year’s report. You can read more about our position in the report here.

What’s more exciting is that we’re just getting started. Since 2018, starting with our Zero Trust Network Access (ZTNA) service Cloudflare Access, we’ve continued to push the boundaries of how quickly we can build and deliver a mature SSE platform. In that time, we’ve released multiple products each year, delivering hundreds of features across our platform. That’s not possible without our customers. Today, tens of thousands of customers have chosen to connect and protect their people, devices, applications, networks, and data with Cloudflare. They tell us our platform is faster and easier to deploy and provides a more consistent and reliable user experience, all on a more agile architecture for longer term modernization. We’ve made a commitment to those customers to continue to deliver innovative solutions with the velocity and resilience they have come to expect from us. If you want to join them on this journey today, contact us to discuss your own SSE journey. 

What is a Security Service Edge?

In general, a Security Service Edge (SSE) provides a helpful framing that gives teams guardrails as they adopt a Zero Trust architecture. The concept breaks down into a few typical buckets:

  • Zero Trust access control: Protect applications that hold sensitive data by creating least privilege rules that check for identity, device posture, and other signals on each and every request or connection.

  • Outbound filtering: Keep people and devices safe as they connect to the rest of the Internet by filtering and logging network traffic, DNS queries, and HTTP requests.

  • Secure SaaS usage: Analyze traffic to SaaS applications and scan the data sitting inside of SaaS applications for potential Shadow IT policy violations, misconfigurations, or data mishandling.

  • Data protection: Scan for data leaving your organization towards destinations that do not comply with your organization’s policies. Find data stored inside your organization, even in trusted tools, that should not be retained or that needs tighter access controls.

  • Employee experience: Monitor and improve the experience that your team members have when using tools and applications on the Internet or hosted inside your own organization.

The SSE space is a component of the larger Secure Access Service Edge (SASE) market. You can think of the SSE capabilities as the security half of SASE, while the other half consists of the networking technologies that connect offices and data centers to each other along with everything that SSE connects. Some vendors only focus on the SSE side and rely on partners to connect customers to their security solutions. Other companies just provide the networking pieces. While today’s announcement highlights our SSE capabilities, Cloudflare offers both components as a unified SASE platform.

How does Cloudflare fit into the SSE space?

Cloudflare’s global network was built for this. We’ve developed a unified, programmable network in which every service runs in every data center, spanning more than 330 cities across the globe. Cloudflare operates within approximately 50 milliseconds of 95% of the Internet-connected population globally. That means that regardless of where your people, apps, and data are located, your Security Service Edge is not far away.

Our SSE services operate on the same infrastructure and locations that support many of the world’s most prominent Internet platforms. We’ve integrated proven strengths including the world’s fastest DNS resolver, our robust serverless compute platform, intelligence from our leading Web Application and API Protection (WAAP) platform and advanced global traffic routing capabilities developed as a result of proxying and protecting approximately 20% of websites. Our architecture ensures single-pass inspection, regardless of how customers connect. We also consistently hear that this performance is core to why customers chose Cloudflare. When customers choose Cloudflare, they’re choosing a unified, resilient platform built for the future.

By building our SSE platform on top of our own network, it puts Cloudflare in the driver’s seat. Whether that’s implementing best practices like IPv6, incorporating new technologies like WireGuard or MASQUE, or safeguarding against the future with post-quantum encryption, by building on our own network we’re able to react quickly as new Internet security standards mature.

Customers can rely on Cloudflare to solve a broad range of security problems represented by the SSE category. They can also just start with a single component. We know that an entire modernization journey can be an overwhelming prospect for any organization. While all the use cases below are built to work better together, we make it simple for teams to start by just solving one problem at a time.

Zero Trust access control

Traditional VPNs have been the backbone of enterprise remote access for decades. However, organizations are rapidly moving away from VPNs due to security vulnerabilities, performance bottlenecks, and poor user experience. As businesses adopt Zero Trust principles, they expect modern solutions that:

  • Improve security posture by enforcing least privilege access and per-resource authorization, eliminating dependence on perimeter-based defenses

  • Enhance user experience with seamless, high-performance connectivity.

  • Reduce complexity and operational overhead by consolidating tools and automating access policies.

Cloudflare enables identity-driven, context-aware policies which replace the traditional castle-and-moat model that come with VPN-based solutions. Applications can be made available to employees as well as third parties through a completely clientless deployment. Policies can also be applied to the applications that sit outside your infrastructure to ensure a consistent experience across SaaS applications as well. 

By mid-2026, we plan to ship a number of new access control capabilities, including:

  • Identity provider (IdP) agnostic multi-factor authentication (MFA): Admins can enforce step-up MFA without having to direct a user back to an identity provider.

  • Just-in-time access controls: Review and approve timely access requests to sensitive resources. Users can request access via tools like Slack and Google Chat.

  • Browser-based RDP: Traditionally, vendors provide a limited number of PoPs which can support clientless RDP. With Cloudflare, customers get highly performant clientless RDP from the browser by connecting to any of Cloudflare’s data centers. This feature enables access to RDP targets without any software installed on the user’s machine.

Secure Web Gateway and DNS filtering

For decades, organizations relied on on-prem hardware firewalls to secure Internet access. Like applications, users have moved beyond the perimeter and cloud-based security services have become essential. Modern businesses expect solutions that:

  • Protect users across locations from malware, ransomware, and other Internet threats

  • Enforce those protections with real-time, comprehensive threat intelligence that adapts with emerging attack vectors

  • Reduce management complexity while maintaining granular policy control across the entire network

Cloudflare Gateway, our secure web gateway (SWG), inspects and filters DNS, network, HTTP, and egress traffic with consistent protections across the Internet and internal resources. Customers adopt our SWG to block threats across remote and office workers, enforce acceptable use policies, encrypt traffic, and block unauthorized SaaS and cloud destinations. In a single-pass architecture, all traffic is verified, filtered, and inspected without the performance penalties seen with hardware-based firewalls and proxies. Threat intelligence is derived from unique real-time visibility across our global network, including 4.3 trillion DNS queries per day, which powers AI-backed threat hunting models to identify, for example, new / newly seen domains before other vendors. 

Browser isolation capabilities are also natively built-in, enabling organizations to insulate users from threats online and protect data in applications with a seamless user experience. For example, isolating web browsing safeguards users from unknown threats, including zero-days, while isolating apps like AI tools can restrict oversharing of proprietary information.

Customers can get started with a variety of deployment methods including device agents, network locations, PAC files, or DNS over HTTPS (DoH) endpoints. Regardless of implementation, consistent policy enforcement and comprehensive logging is easily accessible through our dashboard, our SQL-based Log Explorer experience, or third-party tools via LogPush.

By mid-2026, we plan to ship a number of new filtering and traffic handling capabilities, including:

  • Deep packet inspection to apply filtering to non-standard ports for protocols like HTTP, SSH, and many others.

  • Filtering using Fully Qualified Domain Names (FQDNs): Admins will no longer need to filter packets or egress connections based on destination IP addresses. They will be able to use the FQDN, application name, or destination category with the egress and network policy builders.

  • Identity + PAC files, providing identity-based filtering without having to install the device client.

Cloud firewall

Our comprehensive cloud firewall delivers “firewall as a service” protection that helps organizations manage traffic flows globally. All traffic passing through Cloudflare has firewall policies evaluated first, thus providing the first layer of defense, eliminating unnecessary/unwanted traffic before being further evaluated against security policies. The Cloudflare firewall applies configuration changes globally in seconds, thus providing immediate response to emerging needs. With Cloudflare’s network and data center capacity, you get virtually limitless firewall capacity, without the constraints of traditional hardware firewalls, making it a vital component of your Zero Trust and defense-in-depth architecture.

Inline and API-based CASB

SaaS applications relieve IT teams of the burden to host, maintain, and monitor the tools behind their business. However, they also create entirely new headaches for corresponding security teams. Modern organizations need solutions that:

  • Provide visibility into unauthorized application usage that creates compliance and security risks

  • Enable granular control over data flows within both sanctioned and unsanctioned applications

  • Automate discovery and remediation of security misconfigurations in approved SaaS tools

Any user in an enterprise now needs to connect to an application on the public Internet to do their work, and some users prefer to use their favorite application rather than the ones vetted and approved by the IT department. This kind of Shadow IT infrastructure can lead to surprise fees, compliance violations, and data loss.

Cloudflare offers comprehensive scanning and filtering to detect when team members are using unapproved tools. With a single click, administrators can block those tools outright or control how those applications can be used. If your marketing team needs to use Google Drive to collaborate with a vendor, you can quickly apply a rule that makes sure they can only download files and never upload. Alternatively, you can allow users to visit an application and read from it while blocking all text input. Cloudflare’s Shadow IT policies offer easy-to-deploy controls to help manage how your organization uses the Internet.

Beyond unsanctioned applications, even approved resources can cause trouble. Your organization might rely on Microsoft OneDrive for day-to-day work, but your compliance policies prohibit your HR department from storing files with employee Social Security numbers in the tool. Cloudflare’s Cloud Access Security Broker (CASB) can routinely scan the SaaS applications your team relies on to detect improper usage, missing controls, or potential misconfiguration.

By mid-2026, we look forward to bringing our customers a slew of new capabilities designed to give teams even better visibility and control over their SaaS and cloud applications, including:

  • Robust remediation capabilities: Resolve detected issues right from the dashboard, both automatically and on-demand with a single click.

  • Advanced workflows: Configure automated behavior when new issues are detected, like custom alerting outputs and business justification prompts.

  • User and Entity Behavior Analytics (UEBA) & suspicious activity monitoring: Monitor live events across your SaaS apps and detect anomalous/suspicious activity that could indicate compromise.

Data security

Over the past year, CIOs and CISOs have consistently identified data protection as a top concern, particularly regarding artificial intelligence and large language models. As organizations increasingly rely on cloud services and AI tools, they require modern solutions that:

  • Protect sensitive information across all environments without hampering productivity

  • Provide visibility into how data flows through both internal and external systems

  • Enforce consistent security policies that adapt to evolving regulatory requirements

Cloudflare provides comprehensive visibility and control over data movement and data at rest. This helps organizations avoid the financial impact and reputational consequences of data loss and theft.

Our data security is an integral component of our SASE platform, providing granular control over how users interact with applications. This approach allows organizations to establish nuanced policies that safeguard sensitive information without completely blocking access to productivity-enhancing technologies.

We are introducing a number of exciting data protection capabilities by mid-2026, including AI-based DLP detections, delivering simple, innovative forensics, classifying sensitive data in the public cloud, and innovative, preventative cloud security controls. These features provide administrators with robust controls while maintaining the seamless performance and user experience that organizations expect from Cloudflare. 

Digital experience monitoring

Organizations today struggle with limited visibility into their users’ digital experiences. When performance or availability issues arise, internal support teams often lack the tools to determine whether problems originate in the first, middle, or last mile, resulting in multiple support tickets and delayed resolutions.

Cloudflare addresses this challenge with a comprehensive monitoring toolkit built on the same systems we use to manage our massive global network in-house. This solution empowers IT teams to:

  • Collect on-demand forensic and diagnostic information

  • Systematically gather telemetry data

  • Analyze patterns to anticipate issues before they impact productivity

Cloudflare provides unmatched insight into Internet outages and performance trends that affect your users. This intelligence allows administrators to refine their deployments and quickly identify whether issues are localized to their environment or part of broader global disruptions.

By mid-2026, we plan to ship a number of new digital experience monitoring capabilities, including:

  • Real user monitoring (RUM) that measures the performance of every user’s request.

  • Advanced monitoring for communication applications like Zoom and Microsoft Teams.

  • Contextualizing user performance in terms of global Internet performance data.

Built for what’s next

Security Service Edge forms a critical component of modern enterprise protection, but organizations have modernization requirements across their network infrastructure. Cloudflare designed our capabilities with these needs in mind, because we deliver true convergence of both networking and security from our connectivity cloud.

Across the industry, we’ve seen many instances where vendors start with either networking or security as their primary focus, and acquire a vendor with an entirely different architecture to enter the SASE market. In such scenarios, there is no convergence with security and networking, because internal traffic is handled through different security controls than the cloud traffic.

Cloudflare delivers networking services using the same global data centers and backbone as our security components. Our composable architecture ensures all of our services are designed to work together, in any order. This means that your security and networking stays consistent and provides a common destination for your SASE journey, no matter where you start. 

We’re proud of the work that we’ve done to solve customer problems. Cloudflare continues to receive industry-wide recognition, earning additional positions in 2024 for our comprehensive suite of security solutions beyond SSE, built for the enterprise.

We believe this recognition underscores our position as a pioneering security and networking platform built for tomorrow’s challenges. When organizations choose Cloudflare, they gain more than just another SSE vendor; they’re establishing a partnership with a holistic platform capable of addressing their broader spectrum of requirements for both public and private resources, both today and in the future.

How does that impact customers?

Tens of thousands of organizations trust Cloudflare to secure their teams every day.  We talk to customers directly about that feedback, and they have helped us understand why CIOs and CISOs choose Cloudflare One. For some teams we offer a cost-efficient opportunity to consolidate point solutions. Others appreciate that the ease-of-use means that many practitioners have set up our solution before they even talk to our team. We know that speed matters when we are 46% faster than Zscaler, 56% faster than Netskope, and 10% faster than Palo Alto Networks.

What’s next?

We kicked off 2025 with a week focused on new security features that teams can begin deploying now. In the year ahead, look forward to announcements for our Secure Web Gateway, data protection capabilities, digital experience monitoring, and our inline and API CASB tools. And stay tuned for exciting innovations with AI-driven analytics and monitoring tools, too.

Our commitment in 2025 is the same as it was in 2024. We are going to continue to help your teams solve more security problems so that you can focus on your own mission.

Ready to hold us to that commitment? Cloudflare offers something unique among the players in this space — you can start using nearly every feature in our SSE platform right now at no cost. Teams of up to 50 users can adopt the solution for free to jumpstart a proof of concept. We believe that organizations of any size should be able to quickly and easily start their journey to modernize security.

Footnotes:

1 Gartner, Magic Quadrant for Security Service Edge, Analyst(s): Charlie Winckless, Thomas Lintemuth, Dale Koeppen, Charanpal Bhogal, May 20, 2025

2 Gartner, Magic Quadrant for Cloud Application Platforms, Analyst(s): Tigran Egiazarov, Mukul Saha, Anne Thomas, Steve Schwent, November 1, 2024

3 Gartner, Magic Quadrant for Email Security Platforms, Analyst(s): Max Taggett, Nikul Patel, Franz Hinner, Deepak Mishra, December 16, 2024

4 Gartner, Magic Quadrant for Single-Vendor SASE, Analyst(s): Andrew Lerner, Neil MacDonald, Jonathan Forest, Charlie Winckless, July 3, 2024

GARTNER is a registered trademark and service mark of Gartner, Inc. and/or its affiliates in the U.S. and internationally, and MAGIC QUADRANT is a registered trademark of Gartner, Inc. and/or its affiliates and are used herein with permission. All rights reserved.

Gartner does not endorse any vendor, product or service depicted in its research publications, and does not advise technology users to select only those vendors with the highest ratings or other designation. Gartner research publications consist of the opinions of Gartner’s research organization and should not be construed as statements of fact. Gartner disclaims all warranties, expressed or implied, with respect to this research, including any warranties of merchantability or fitness for a particular purpose.

Threats don’t wait, neither should you: Mastering Emergent Threat Response Validation

Post Syndicated from Ed Montgomery original https://blog.rapid7.com/2025/05/23/mastering-emergent-threat-response-validation/

Cybersecurity is a team sport

Threats don’t wait, neither should you: Mastering Emergent Threat Response Validation

In cybersecurity, no one fights alone. Defending against modern threats requires seamless collaboration, real-time intelligence, and precision execution—just like a well-coordinated sports team. That’s why Rapid7 Labs and our Vector Command team work together to stay ahead of adversaries, ensuring security teams have the insights and capabilities needed to respond effectively. While Rapid7 Labs uncovers emerging threats and delivers cutting-edge research, Vector Command puts that intelligence to work—validating response strategies, optimizing defenses, and ensuring organizations are ready when it matters most. Because in cybersecurity, the best defense is a well-prepared team.

What is an Emergent Threat Response?

Rapid7’s Emergent Threat Response (ETR) program from Rapid7 Labs delivers fast, expert analysis and first-rate security content for the highest-priority security threats to help both Rapid7 customers and the greater security community understand their exposure and act quickly to defend their networks against rising threats.

The Rapid7 Command Platform displays any emergent threats on our homepage, at the top of the screen, easily visible once you have logged in. Our expert researchers include a blog post to accompany each emergent threat.

We also notify all Managed Service customers after discovering new Common Vulnerabilities and Exposures (CVEs). This notification includes known information about the CVE, steps to protect your environment and updates on Rapid7’s response.

Threats don’t wait, neither should you: Mastering Emergent Threat Response Validation
Figure 1: An example of how the Emergent Threat message is displayed on our Command Platform home page
Threats don’t wait, neither should you: Mastering Emergent Threat Response Validation
Figure 2: A close-up view of the actual Emergent Threat message with supporting blog post.

Why is ETR critical?

Emergent threat response validation is critical because cyber threats evolve at a relentless pace, often outpacing traditional security measures. Without continuous testing and refinement, even the most advanced security tools can fall short when faced with real-world attacks. By proactively validating threat response strategies, organizations can identify gaps, fine-tune automation, and ensure that security teams are ready to act with speed and precision. This not only minimizes downtime and damage but also strengthens overall resilience, enabling businesses to stay ahead of adversaries rather than scrambling to react after an incident has already occurred. In today’s threat landscape, preparedness isn’t optional—it’s the difference between containment and catastrophe.

Threats don’t wait, neither should you: Mastering Emergent Threat Response Validation
Figure 3: Emergent Threat Alert message.

How can Vector Command help?

This is the value of an always-on, managed red team service. We continuously test your defenses against the latest ETRs, to see if we can breach your network before threat actors do. If we’re successful, we’ll show you how—and provide actionable remediation guidance.

We’d love to highlight the many organizations that have benefited from this capability with Vector Command, however, we respect their privacy.

One example we can share: a global professional services firm adopted Vector Command for this exact use case. As a frequent target of advanced persistent threats, their security team recognized the value of proactive testing of their resilience.

DORA compliance was also a key driver for this client, given their customer footprint in the EU and the requirement to have reporting. DORA compliance reports demonstrate how financial entities meet regulatory expectations around ICT risk management, incident handling, and third-party oversight—ensuring operational resilience.

With Vector Command, we deliver ongoing external network penetration testing. For some customers, this alone is enough to demonstrate to auditors that they are actively validating their defenses in alignment with DORA.

CTEM and Validation

The leading industry analyst, Gartner®, has said, “security operations managers should go beyond vulnerability management and build a continuous threat exposure management program to more effectively scope and remediate exposures”.

Threat exposure management involves identifying, assessing, and mitigating exposures within an organization’s digital environment. CTEM has emerged as a dynamic program designed to help teams manage their expanding attack surface and maintain a consistent, actionable security posture.

The fourth phase of CTEM is the validation phase and this is where always on red teaming, like Vector Command becomes essential.

Rapid7 also supports the second, third and fifth phases of CTEM through our Exposure Command and Exposure Command Advanced, both launched in August 2024.

Threats don’t wait, neither should you: Mastering Emergent Threat Response Validation
Figure 4: Continuous Threat Exposure Management | Source: Gartner 796532_C

Take command of your attack surface

This is the fourth post in our deep dive blog series exploring key capabilities of Vector Command. We hope you’ve found it valuable—and if you have feedback or questions, we’d love to hear from you.

Rapid7 brings together world-class expertise –  from our Labs researchers and red teamers to the superstars who work across our multiple SOC’s.

If you missed our most recent virtual Take Command 2025 summit, the session, “Outpacing the adversary: Red teaming in a complex threat landscape” is still available on demand. You’ll hear firsthand from industry expert, Will Hunt and Rapid7 principal security consultant, Aaron Herndon.

We’ve also created a self-guided product tour for Vector Command—available anytime for a hands-on look at the platform.

Vector Command: Request Demo ▶︎

Ready to see how continuous red team managed services can ensure your potential attack pathways are remediated before they can ever be exploited?


GARTNER is a registered trademark and service mark of Gartner, Inc. and/or its affiliates in the U.S. and internationally and is used herein with permission. All rights reserved.

Gartner, “How to Grow Vulnerability Management Into Exposure Management”, November 2024 (For Gartner subscribers only)

Teaching digital literacy without devices

Post Syndicated from Ben Hall original https://www.raspberrypi.org/blog/teaching-digital-literacy-without-devices/

Lack of access to devices presents teachers with challenges in any setting. In schools, money is often limited and digital technology may not be the priority when buildings need maintenance or libraries need replenishing. This issue is particularly important when the very subject you teach relies on and relates to devices that you may have limited or no access to.

An educator helps students with a coding task in a classroom.

It must be frustrating for teachers in this situation to see marketing campaigns from companies showing how their curriculum offering will use the very latest in robotics, AI, or media production, when the teachers’ reality is that they don’t have anything like the means or resources to deliver this. 

Fortunately there are approaches that can help. Below I outline some of the ways we are working with teachers to make the teaching of computing and digital literacy less resource-heavy and more accessible and equitable. 

Schools in Kenya: A case study 

Our work with Kenyan teachers has brought the access issue into sharp focus for us. We are currently developing free resources to deliver the Kenyan curriculum to schools in Mombasa and the Frontier Counties. There are big contrasts both between and within these two areas of the country. Some schools are well equipped with digital technology, while others have very little access to any computing devices; in these schools, smartphones play a crucial role.

Students code in Scratch on a computer.

With that in mind, the curriculum resources we develop suggest class activities that make the most of limited devices, such as the use of projected demonstrations. We also provide a step-by-step guide to computing tasks, with screenshots, to guide learners through the tasks conceptually. This ensures learners understand the process and can apply their new knowledge once they gain access to the necessary devices. 

We make these resources available online and in downloadable documents. This means the resources can be taken offline and taught in places without stable internet connection. We are also careful to limit file sizes, to make downloads more accessible. Wherever possible, our resources are device-agnostic, so that they can be accessed on a wide range of devices, including personal devices such as mobile phones.

A close-up shot shows a person's hand holding a small red LED light, which is illuminated.

As well as tailoring curriculum resources, we have also adapted our teacher training to make it more accessible for people with less experience of using computing devices. For example, during a recent project coaching community trainers in Mombasa, we emphasised activities that improve digital skills on various devices. This meant that when passing the training on to other teachers, the community trainers had a broader set of skills across a wider range of devices.

An educator delivers a lesson to students in a classroom.
You’ll be able to read more about the impact of our work with Kenyan schools in an upcoming blog post.

Unplugged activities

Even computing-specific concepts such as a programming construct can, to a degree, be taught with very limited access to devices. Unplugged activities, where no digital technology is required, can be used to introduce fundamental concepts such as sequencing and repetition.

A group of men holding a string.

For example, you can ask learners to recognise patterns in repeating sequences of colours and identify how to describe the sequences without repeating the colours many times. While it is good practice to link the learning from an unplugged activity back to a plugged activity, students will still benefit when that is not possible. 

Emulators 

There are also a significant number of devices which offer online emulator apps that mirror the functions of the physical device. Consider Bee-Bot floor robots, which can be relatively expensive to purchase and may get damaged in a classroom. If you don’t have the physical device, its emulator app provides a similar experience.

Three young learners present their coding project.

Similarly, the micro:bit, a versatile microcontroller for young people, can be emulated in the MakeCode programming environment, including all its buttons and sensors. There are also numerous emulators which enable you to make and test your own circuits using a variety of hardware platforms. 

What do you actually need? 

Sometimes it can be helpful to look up what devices you actually need — they might not be as expensive as you think. General-purpose, single-board computers such as Raspberry Pi can be bought new for less than £25, and more powerful models still under £50.

A young learner is building his project at a Coolest Projects event.

Similarly, microcontrollers such as Raspberry Pi Pico, micro:bit, or Crumble, range from about £5 to £20 per device. Accessories such as LEDs, jumper leads, motors, and buzzers are also reasonably priced. They can be a relatively low-cost entry into physical computing and robotics, especially if you pair them with craft materials or share devices between students.

Make the most of it 

However limited your access to devices is, I encourage you to:

  • Look out for partners or solution providers that prioritise inclusivity and accessibility in their resources
  • Consider whether you can make activities accessible on a wider range of devices and use what students may already have (check out the OctoStudio app for smartphones for example)
  • Use unplugged activities, and relate them back to plugged devices when possible
  • Look up devices which might be more affordable than you realised

If you have your own tips to share with fellow teachers, please comment below.

More on digital literacy

You can discover our free teacher training and classroom resources, and read about how we’ve integrated digital literacy in The Computing Curriculum.

A version of this article appears in the newest issue of Hello World magazine, which is all about digital literacy. Explore issue 26 and download your free PDF copy today.
You can also listen to our recent Hello World podcast episode exploring three teachers’ digital literacy tips for the classroom.

The post Teaching digital literacy without devices appeared first on Raspberry Pi Foundation.

Security updates for Friday

Post Syndicated from corbet original https://lwn.net/Articles/1022352/

Security updates have been issued by Fedora (dotnet9.0, dropbear, ghostscript, nbdkit, openssh, python-watchfiles, rpm-ostree, yelp, yelp-xsl, and zsync), Oracle (firefox and kernel), Red Hat (osbuild-composer), Slackware (aaa_glibc and mozilla), SUSE (chromedriver, open-vm-tools, postgresql14, python-cryptography, and thunderbird), and Ubuntu (linux-aws, linux-hwe-5.4, python, and sqlite3).

Гласовете на Америка – брой 1

Post Syndicated from Йоанна Елми original https://www.toest.bg/glasovete-na-amerika-broy-1/

Тук стой като древен камък
и виж как гаснат светлините, чуй гласа на океана.
Ненавист и мъка сграбчват Европа и Азия
и морският вятър е леден.

Настъпва нощ: върви си вкъщи,
опитай се да хванеш по радиото новините.
Чуваш ли ги, гласовете на Америка: наивни,
властни, лицемерни и обречени.

Робинсън Джефърс, Избрана поезия, прев. Николай Г. Попов


Гласовете на Америка – брой 1

Преди повече от половин век почти забравеният днес американски поет отшелник Робинсън Джефърс описва своята „изчезваща република“ като затворник в „калъпа на своята вулгарност, втвърдяваща се в империя“. Стиховете на Джефърс дават името на този бюлетин, защото Америка има повече от един глас; повече от едногласието на собствените си митове за американската мечта, на героичната победителка над нацизма, на добрата страна в Студената война. Но повече и от монофонията, която представя антизападната пропаганда в България. 

През изминалите три месеца от встъпването в длъжност на американския президент Доналд Тръмп Европа и светът се справят със смяната в тона и с новия глас, с който говори Америка. Дори вътре в държавата хората не могат да асимилират склонността на новата администрация да тества границите. Вярата на света и на самите американци в системата от проверки и баланси и способността им да озаптят всеки самозабравил се политик все още е силна. 

Дали? 

И ако да – докога?

Отсяване на същественото 

През 2018 г. Стивън Банън, един от стратезите (де факто вече бивш) на Доналд Тръмп, се похвали с тактиката на „наводняване на зоната“ – засипването с информация на демократите и на медиите, които републиканците възприемат като опозиционни. 

Джеси Уотърс, един от водещите на вечерното шоу на консервативния канал FOX News, каза през февруари тази година:

Ние водим модерна информационна война срещу лявото, а те използват тактики от 90-те. Те организират мънички пресконференции, мънички протести. Крещят в нищото по MSNBC [телевизия с продемократически уклон]. Това се нарича командване и контрол отгоре надолу, top-down. Имаш опорките от вестника, слагаш ги в новините и те изчезват. Това, виждаме вдясно, е асиметрично – органична партизанска война. Някой казва нещо в социалните мрежи, [Илън] Мъск го ретуитва, [Джо] Роган го вкарва в подкаста си, Fox го излъчва и така милиони го виждат. Това е свободата на парите, говорим за излъчване на информация. Те [демократите] потискат информация. Ако гледате CBS News, там дори не говорят за скандалите с парите. Трансджендъри от Шри Ланка получават електрически автомобили и това струва милиони? [Твърдението е проверено и се смята за преувеличено, с умишлено премълчан контекст.] Те няма да ви кажат за това. Ние ще ви кажем. Защото е необичайно, закачливо, интересно и бързо става популярно. В това е разликата.

В първите 100 дни от мандата си Тръмп подписа 143 президентски указа – повече от всеки друг президент в историята на САЩ. Заглавията, често шокиращи, се променяха на всеки час, а спекулациите с катастрофалните последици на някои от заповедите – както и реалните последици от други – наводниха информационното пространство. Паниката и немощта на опозицията доведоха до силно емоционални реакции в различни посоки. Бомбастичното съдържание на указите и информационната стратегия на Белия дом и на консервативната медийна екосистема пък видяха решения там, където всъщност се създадоха повече проблеми. 

Бавната, съсредоточена и критична журналистика остава сред най-добрите антидоти срещу силно поляризираната и емоционална страна на социалните мрежи и срещу информационната война, която се води онлайн и през различни медийни източници. Това е и целта на този бюлетин. А за встъпителния брой едва ли има по-подходяща тема от 

резултатите от първите 100 дни управление на президента Тръмп 

За този период той е предприел общо 247 еднолични инициативи, свързани с устройството на държавата. Associated Press анализира 196 от тях: 78 са частично или изцяло блокирани, 72 са на изчакване за съдебно решение и 46 са в сила. Целият свят следи в актуално време ефективността на американското правораздаване през танца между президента, който тества границите на правомощията си, и съдебната система, чиято цел е да го удържи. 

Доналд Тръмп изпълнява обещанията си от предизборната кампания: той заложи на позиция срещу имиграцията, на депортации, намаляване на харчовете на федералното правителство, връщане на производството в САЩ и налагане на мита, както и на прекратяването на войните в Газа и Украйна. Освен това Тръмп се зарече да реформира университетите, да свали цените, да се бори срещу инфлацията и да въведе данъчна реформа

Южната граница, имигрантите, депортациите 

Наблюдава се драстичен спад в потока от нелегални мигранти по южната граница на САЩ. Това вероятно е най-добре спазеното обещание на настоящата администрация. Не така стоят нещата с „масовите депортации“, обещани от Тръмп – броят на депортирани нелегални мигранти остава по-нисък от броя им по времето на администрацията на Джо Байдън. Белият дом твърди, че 75% от депортираните имат криминални прояви в страната, но журналистически разследвания показват, че с провинения са едва 25% от 238-те мигранти, изпратени в мегазатвора в Ел Салвадор. Целите на Тръмп да депортира 15–20 млн. нелегални мигранти изглеждат недостижими – не само защото съдилищата, включително Върховният съд, блокират много от механизмите, които Тръмп се опитва да използва, а и защото това би унищожило икономиката на страната. В допълнение, задържането и тормозът на легално влизащи в страната хора разбираемо разбунват духовете както в САЩ, така и по света. 

Продължава и казусът с връщането на Килмар Абрего Гарсия, изпратен по погрешка в затвор за терористи. Аргументът на администрацията на Тръмп е, че неговата депортация е в правомощията на президента да управлява външната политика. Експерти съдии и Върховният съд на САЩ обаче подчертават нуждата от справедлив процес, какъвто Гарсия и други депортирани не получават, и изтъкват възможни нарушения на закона от страна на администрацията на Тръмп. 

Намаляване на харчовете на федералното правителство 

Още в първите дни на мандата си Доналд Тръмп назначи милиардера Илън Мъск в Департамента за правителствена ефективност (DOGE) заедно с друг американски предприемач – Вивек Рамасвами, който напусна броени дни по-късно. Според собствените им заявки в последвалите седмици и месеци DOGE са орязали около 160 млрд. долара федерални разходи. 

Това число бе променено няколко пъти и остава далеч дори от ревизираните цели, които първоначално бяха много по-високи. Мъск обеща, че новият орган, чийто неясен статут също бе разискван от експерти и от съдебните органи, ще спести 2 трлн. долара, което бе свалено до 1 трлн., а накрая до 150 млрд. до края на следващата фискална година. Разследвания показаха, че от обявените спестени 160 млрд. едва 61,5 мрлд. са с разбивка по пера и само за 32,5 млрд. има подробни разписки, сметки и документи. Междувременно независим анализ показва, че DOGE всъщност струва 135 млрд. долара на данъкоплатците. 

В допълнение, департаментът получава достъп до личните данни на всички американци. Критици посочват, че това представлява не само етичен конфликт, но и конфликт на интереси с оглед на бизнесите на Илън Мъск, в които има търговия с данни и информация. В много случаи съкратените и уволнените правителствени служители (или поне част от тях) биват върнати на работа дни по-късно. Това повдига редица въпроси относно ефективността и метода на работа на Мъск и подчинените му, които нямат опит в държавното управление. Агенцията на Мъск не се радва на широка обществена подкрепа дори сред републиканците, а самият той заяви, че ще се отдръпне от държавна дейност, за да се фокусира върху бизнеса си. 

Митата 

Проследяването на митата, наложени от президента Тръмп, се оказва сложна задача. Още при встъпването си в длъжност на 20 януари той заяви, че ще наложи мита от 25% на вносни стоки от Канада и Мексико. На 26 януари Тръмп обяви в социалните мрежи, че ще наложи мита и на Колумбия, като след медиен сблъсък между държавните глави мерките бяха отменени. Митата за Канада и Мексико влязоха в сила на 1 февруари заедно с мито от 10% за стоки от Китай, а на 2 февруари Тръмп за пръв път използва аргумента за краткотрайните жертви, които американците ще трябва да направят в името на новия държавен ред (но добави, че може и да не трябва да правят жертви). На следващия ден Тръмп сложи митата на пауза. На 4 февруари влязоха в сила митата за Китай. Хронологията продължава в подобен ритъм до 9 април, когато Тръмп наложи мита от 104% на китайски стоки заедно с мита за други държави и де факто ескалира търговската война… След което в същия ден отмени митата за всички, освен за Китай. 

Тази част от текста бързо омръзва. Същината е, че мита в сила в момента има, но към 29 април Тръмп подписа два указа, които отменят някои от митата за автомобилните производители и променят системата на събиране на мита върху определени стоки, като алуминий и стомана. На 12 май Китай и САЩ обявиха, че отменят значителна част от реципрочните си мита. Ефектът от политиките през последните няколко месеца ще започне да се усеща в САЩ съвсем скоро, тъй като доставките по веригата отнемат около месец и половина път по море до големите пристанища на западния бряг и след това още две седмици до месец към източния. 

Според експертите митата ще генерират значителни приходи – към 5,2 трлн. долара за период от 10 години, като тези приходи биха могли да се използват за изплащане на държавния дълг и за насърчаване на частните инвестиции. Тъй като митата тежат на търговците и купувачите обаче, специалистите са единодушни, че „всички домакинства ще пострадат“. Разбира се, ако митата изобщо се задържат. 

Специалистите са единодушни и че това със сигурност ще попречи на осезаемото сваляне на цените и борбата с инфлацията, за което ще пишем в следващия текст заедно с темите за войните в Газа и Украйна, данъчните и университетските реформи. А дотогава ви оставям с част от историята на САЩ, с което ще завършвам всеки материал от поредицата – просто за да се успокояваме, че нищо никога не е начало или край, а просто безкрайно и понякога изтощително повторение. 

Гласът на миналото

Гласовете на Америка – брой 1
Карикатура на Хърбърт Хувър, който язди две враждуващи крила на партията, покрити под символа на републиканците – слона. Надписът отдолу гласи: „Чакай, че забравих – ние за или против митата сме?“

Законът за митата от 1930 г., познат като Smoot–Hawley Tariff Act, е подписан от американския президент Хърбърт Хувър на 17 юни. Той налага мита на над 20 000 вида стоки в опит да защити американския пазар от вносните продукти малко след началото на Голямата депресия, която започва през октомври 1929 г. Хувър подписва закона въпреки съветите на множество старши икономисти и под партийно влияние. Вместо да подкрепят американската икономика, митата задълбочават депресията, защото търговските партньори на САЩ отговарят със собствени мита, което води до спад в износа на САЩ и в световната търговия. Днес законът се смята за учебникарски пример за протекционистка политика. 


Абонирайте се, за да получавате този бюлетин на електронната си поща в момента, в който излезе!

Вече сте регистриран потребител на Toest.bg? Можете директно от настройките на бюлетините в своя профил да изберете „Гласовете на Америка“ или да натиснете бутона по-долу:

Още нямате профил в Toest.bg? Регистрирайте се само с няколко клика:

The collective thoughts of the interwebz