Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/workflows/publish-java-agent.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Publish Java Agent Layers

on:
push:
tags:
- v**_java-agent

jobs:
publish-java-agent:
runs-on: ubuntu-latest
steps:
- name: Check Tag
id: java-agent-check-tag
run: |
if [[ ${{ github.event.ref }} =~ ^refs/tags/v[0-9]+(\.[0-9]+)*_java-agent ]]; then
echo "match=true" >> $GITHUB_OUTPUT
fi
- uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: arm64, amd64
- name: Publish Java Agent Layer
if: steps.java-agent-check-tag.outputs.match == 'true'
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: |
cd java-agent
./publish-layers.sh
Comment on lines +10 to +30

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 19 days ago

In general, the problem is fixed by defining explicit permissions for the workflow or specific job, limiting the GITHUB_TOKEN to only what is required. For this workflow, the steps only need to read repository contents (for actions/checkout) and do not require any write operations via GITHUB_TOKEN. Therefore, we can safely set contents: read as the job (or workflow) permissions.

The best minimal change without altering functionality is to add a permissions: block at the job level for publish-java-agent. This keeps the change tightly scoped and clearly associated with the job CodeQL flagged. We will insert:

    permissions:
      contents: read

directly under runs-on: ubuntu-latest in .github/workflows/publish-java-agent.yml. No additional imports or methods are required, because this is purely a YAML configuration change for GitHub Actions.

Suggested changeset 1
.github/workflows/publish-java-agent.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/publish-java-agent.yml b/.github/workflows/publish-java-agent.yml
--- a/.github/workflows/publish-java-agent.yml
+++ b/.github/workflows/publish-java-agent.yml
@@ -8,6 +8,8 @@
 jobs:
   publish-java-agent:
     runs-on: ubuntu-latest
+    permissions:
+      contents: read
     steps:
       - name: Check Tag
         id: java-agent-check-tag
EOF
@@ -8,6 +8,8 @@
jobs:
publish-java-agent:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Check Tag
id: java-agent-check-tag
Copilot is powered by AI and may make mistakes. Always verify output.
48 changes: 48 additions & 0 deletions java-agent/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Java Agent Lambda Layer

## Description

Deployment scripts for deploying a lambda layer that attatches the New Relic Java Agent with serverless mode enabled.

## How to build & publish locally

First make sure you are in the java-agent directory. Run `cd java-agent`.

### Updating versions.sh (Skip if using a local agent jar)
First go into `versions.sh` and check the Java Agent version. Make sure it is the correct one you will use as you will download it from the downloads site.

For example, to use agent version `9.1.0`, set this in `versions.sh`:
```
NEWRELIC_AGENT_VERSION=9.1.0
```

### Building locally

If you are downloading the agent from downloads site, run `./build-layers.sh`.
If you are using a locally built agent Jar, run `./build-layers.sh /path/to/agent/jar` where `/path/to/agent/jar` is your path to the agent jar.

You will see a `/dist` directory created with zip files for each lambda layer deployed:

- java-agent.x86_64.zip
- java-agent.arm64.zip
- java-agent-slim.x86_64.zip
- java-agent-slim.arm64.zip

You can manually upload them to your AWS console and deploy them into your lambda provided they are using a supported Java Version.

### Building locally

The `publish-layers.sh` script builds and publishes your lambda layers.

To publish your lambda layers, you need to follow the steps in the [local testing guide](https://newrelic.atlassian.net/wiki/spaces/APM/pages/5337088128/New+Relic+Lambda+Layers+-+Local+Testing+Guide) to set up your AWS account and the libBuild.sh script. **Make sure your AWS account has the correct IAM permissions needed to follow these steps as well.**

If you are publishing using the agent from downloads site, run `./publish-layers.sh`.
If you are publishing using a locally built agent Jar, run `./publish-layers.sh /path/to/agent/jar` where `/path/to/agent/jar` is your path to the agent jar.

**Important:** You may have to comment out sections of the publish scripts that deploy to an architecture unsupported on your machine. For example, X86_64 machines may have to comment out sections that deploy arm64 layers. Vice versa with ARM64 machines.

You will then see the following deployed lambda layers in your AWS console:
- NewRelicAgentJava
- NewRelicAgentJavaARM64
- NewRelicAgentJava-slim
- NewRelicAgentJavaARM64-slim
61 changes: 61 additions & 0 deletions java-agent/build-layers.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env bash

set -Eeuo pipefail

AGENT_PATH=$1
export AGENT_JAR=newrelic.jar

export AGENT_DIR=newrelic
export DIST_DIR=dist
export EXEC_WRAPPER=newrelic-java-handler
export LIB_HANDLER=lib-handler.sh

export JAVA_AGENT_DIST_X86_64=$DIST_DIR/java-agent.x86_64.zip
export JAVA_AGENT_DIST_ARM64=$DIST_DIR/java-agent.arm64.zip

export JAVA_AGENT_SLIM_DIST_X86_64=$DIST_DIR/java-agent-slim.x86_64.zip
export JAVA_AGENT_SLIM_DIST_ARM64=$DIST_DIR/java-agent-slim.arm64.zip

parent_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )

source ../libBuild.sh
source versions.sh

function build-java-agent {
distribution_file=$1
arch=$2
agent_path=$3
java_handler_path=$4
echo "Building New Relic layer for the Java Agent ($arch)"
rm -rf $AGENT_DIR $distribution_file
mkdir -p $DIST_DIR
get_agent $agent_path
download_extension $arch
cp $java_handler_path ./$EXEC_WRAPPER
zip -rq $distribution_file $EXTENSION_DIST_DIR $EXTENSION_DIST_PREVIEW_FILE ./$EXEC_WRAPPER $AGENT_DIR $LIB_HANDLER
rm -rf $AGENT_DIR $EXTENSION_DIST_DIR $EXTENSION_DIST_PREVIEW_FILE ./$EXEC_WRAPPER
echo "Build complete: ${distribution_file}"
}

function get_agent {
agent_path=$1
rm -rf $AGENT_JAR

if [[ -n "$agent_path" ]]; then
echo "Copying agent from $agent_path"
cp ${agent_path} $AGENT_JAR
else
url="https://download.newrelic.com/newrelic/java-agent/newrelic-agent/${NEWRELIC_AGENT_VERSION}/newrelic-agent-${NEWRELIC_AGENT_VERSION}.jar"
echo "Downloading agent from $url"
curl -L $url -o $AGENT_JAR
fi

mkdir -p $AGENT_DIR
mv $AGENT_JAR $AGENT_DIR/$AGENT_JAR
rm -f $AGENT_JAR
}

build-java-agent $JAVA_AGENT_DIST_X86_64 x86_64 $AGENT_PATH ./java-handler-full
build-java-agent $JAVA_AGENT_DIST_ARM64 arm64 $AGENT_PATH ./java-handler-full
build-java-agent $JAVA_AGENT_SLIM_DIST_X86_64 x86_64 $AGENT_PATH ./java-handler-slim
build-java-agent $JAVA_AGENT_SLIM_DIST_ARM64 arm64 $AGENT_PATH ./java-handler-slim
14 changes: 14 additions & 0 deletions java-agent/java-handler-full
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash

set -ef -o pipefail

source /opt/lib-handler.sh

ARGS=("$@")
EXTRA_ARGS=()

setup_agent $ARGS $EXTRA_ARGS

ARGS=("${ARGS[0]}" "${EXTRA_ARGS[@]}" "${ARGS[@]:1}")

exec "${ARGS[@]}"
21 changes: 21 additions & 0 deletions java-agent/java-handler-slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/bash

set -ef -o pipefail

source /opt/lib-handler.sh
ARGS=("$@")
EXTRA_ARGS=()

setup_agent $ARGS $EXTRA_ARGS

export NEW_RELIC_LITE_MODE=true
log_debug "Always setting NEW_RELIC_LITE_MODE to be true"

if [ -z "${NEW_RELIC_CLASS_TRANSFORMER_AWS_LAMBDA_JAVA_CORE_ENABLED}" ]; then
export NEW_RELIC_CLASS_TRANSFORMER_AWS_LAMBDA_JAVA_CORE_ENABLED=true
log_debug "Setting NEW_RELIC_CLASS_TRANSFORMER_AWS_LAMBDA_JAVA_CORE_ENABLED to be true"
fi

ARGS=("${ARGS[0]}" "${EXTRA_ARGS[@]}" "${ARGS[@]:1}")

exec "${ARGS[@]}"
80 changes: 80 additions & 0 deletions java-agent/lib-handler.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/bin/bash

set -ef -o pipefail

function log_debug {
if [[ "$NEW_RELIC_EXTENSION_LOG_LEVEL" == "DEBUG" ]]; then
echo "[NR_JAVA_HANDLER] DEBUG $1"
fi
}

function log {
echo "[NR_JAVA_HANDLER] $1"
}

function setup_agent {
log "Begin detecting java version"
if type -p java; then
log found java executable in PATH
_java=java
elif [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]]; then
log found java executable in JAVA_HOME
_java="$JAVA_HOME/bin/java"
else
log "No java version detected"
fi

if [[ "$_java" ]]; then
version=$("$_java" -version 2>&1 | awk -F '"' '/version/ {print $2}')
log "Verifying JVM version is compatable. Only JVMs versions 17 and up are supported."
log "Java version $version detected"
if [[ "$version" > "17" ]] || [[ "$version" == "17" ]]; then
export JAVA_TOOL_OPTIONS="-javaagent:/opt/newrelic/newrelic.jar ${JAVA_TOOL_OPTIONS}"
log "Attatched New Relic Java Agent"
else
log version is less than 17, will not attatch the New Relic Java Agent
fi
else
export JAVA_TOOL_OPTIONS="-javaagent:/opt/newrelic/newrelic.jar ${JAVA_TOOL_OPTIONS}"
log "Attatched New Relic Java Agent"
fi

########################################

if [ -z "${NEW_RELIC_APPLICATION_LOGGING_FORWARDING_ENABLED}" ]; then
export NEW_RELIC_APPLICATION_LOGGING_FORWARDING_ENABLED=false
log_debug "Setting NEW_RELIC_APPLICATION_LOGGING_FORWARDING_ENABLED to be false"
fi

if [ -z "${NEW_RELIC_CROSS_APPLICATION_TRACER_ENABLED}" ]; then
export NEW_RELIC_CROSS_APPLICATION_TRACER_ENABLED=false
log_debug "Setting NEW_RELIC_CROSS_APPLICATION_TRACER_ENABLED to be false"
fi

if [ -z "${NEW_RELIC_SPAN_EVENTS_COLLECT_SPAN_EVENTS}" ]; then
export NEW_RELIC_SPAN_EVENTS_COLLECT_SPAN_EVENTS=true
log_debug "Setting NEW_RELIC_SPAN_EVENTS_COLLECT_SPAN_EVENTS to be true"
fi

if [ -z "${NEW_RELIC_TRANSACTION_TRACER_COLLECT_TRACES}" ]; then
export NEW_RELIC_TRANSACTION_TRACER_COLLECT_TRACES=true
log_debug "Setting NEW_RELIC_TRANSACTION_TRACER_COLLECT_TRACES to be true"
fi

if [ -z "${NEW_RELIC_APP_NAME}" ]; then
export NEW_RELIC_APP_NAME=lambda-function
log_debug "Setting NEW_RELIC_APP_NAME to be lambda-function"
fi

if [ -z "${NEW_RELIC_LOG_FILE_PATH}" ]; then
mkdir -p /tmp/logs
export NEW_RELIC_LOG_FILE_PATH=/tmp/logs/
log_debug "Setting NEW_RELIC_LOG_FILE_PATH to be /tmp/logs/"
fi

export NEW_RELIC_SERVERLESS_MODE_ENABLED=true
log_debug "Always setting NEW_RELIC_SERVERLESS_MODE_ENABLED to be true"

export NEW_RELIC_ENABLE_AUTO_APP_NAMING=false
log_debug "Always setting NEW_RELIC_ENABLE_AUTO_APP_NAMING to be false"
}
31 changes: 31 additions & 0 deletions java-agent/publish-layers.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/usr/bin/env bash

set -Eeuo pipefail

source ./build-layers.sh

function publish-java-agent {
distribution_file=$1
arch=$2
slim=$3
if [[ $slim != "slim" ]]; then
slim=""
fi
if [ ! -f $distribution_file ]; then
echo "Package not found: ${distribution_file}"
exit 1
fi

for region in "${REGIONS[@]}"; do
echo "Publishing $slim java agent layer in region $region"
publish_layer $distribution_file $region java $arch $NEWRELIC_AGENT_VERSION $slim
done

publish_docker_ecr $distribution_file java $arch $slim
}

publish-java-agent $JAVA_AGENT_DIST_X86_64 x86_64 ""
publish-java-agent $JAVA_AGENT_DIST_ARM64 arm64 ""

publish-java-agent $JAVA_AGENT_SLIM_DIST_X86_64 x86_64 slim
publish-java-agent $JAVA_AGENT_SLIM_DIST_ARM64 arm64 slim
1 change: 1 addition & 0 deletions java-agent/versions.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NEWRELIC_AGENT_VERSION=9.1.0
21 changes: 20 additions & 1 deletion libBuild.sh
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ function download_extension {
function layer_name_str() {
rt_part="LambdaExtension"
arch_part=""


case $1 in
"java8.al2")
Expand All @@ -76,6 +77,12 @@ function layer_name_str() {
"java21")
rt_part="Java21"
;;
"java25")
rt_part="Java25"
;;
"java")
rt_part="AgentJava"
;;
"python3.9")
rt_part="Python39"
;;
Expand Down Expand Up @@ -145,6 +152,9 @@ function s3_prefix() {
"java11")
name="java-11"
;;
"java")
name="nr-java-agent"
;;
"python3.9")
name="nr-python3.9"
;;
Expand Down Expand Up @@ -209,7 +219,7 @@ function agent_name_str() {
"ruby3.2"|"ruby3.3"|"ruby3.4")
agent_name="Ruby"
;;
"java8.al2"|"java11"|"java17"|"java21")
"java8.al2"|"java11"|"java17"|"java21"|"java25"|"java")
agent_name="Java"
;;
"python"|"python3.9"|"python3.10"|"python3.11"|"python3.12"|"python3.13"|"python3.14")
Expand Down Expand Up @@ -290,6 +300,10 @@ function publish_layer {
then compat_list=("dotnet6" "dotnet8" "dotnet10")
fi

if [[ $runtime_name == "java" ]]
then compat_list=("java17" "java21" "java25")
fi

if [[ $runtime_name == "python" ]]
then compat_list=("python3.9" "python3.10" "python3.11" "python3.12" "python3.13" "python3.14")
fi
Expand Down Expand Up @@ -366,6 +380,11 @@ function publish_docker_ecr {
arch_flag=${arch}
fi

if [[ ${runtime_name} == 'java' ]]; then
version_flag=""
arch_flag=${arch}
language_flag="java-agent"
fi
if [[ $runtime_name == "python" || $runtime_name == "nodejs" ]]; then
version_flag=""
arch_flag=${arch}
Expand Down
Loading