Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
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
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,4 @@ module.exports = {
'prefer-template': 'error',
quotes: ['warn', 'single', { allowTemplateLiterals: true }]
}
};
};
9 changes: 5 additions & 4 deletions apps/agent-provisioning/AFJ/scripts/start_agent.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ AFJ_VERSION=${14}
INDY_LEDGER=${15}
INBOUND_ENDPOINT=${16}
SCHEMA_FILE_SERVER_URL=${17}

AGENT_API_KEY="${18}"
ADMIN_PORT_FILE="$PWD/apps/agent-provisioning/AFJ/port-file/last-admin-port.txt"
INBOUND_PORT_FILE="$PWD/apps/agent-provisioning/AFJ/port-file/last-inbound-port.txt"
ADMIN_PORT=8001
Expand Down Expand Up @@ -122,7 +122,7 @@ if [ -f "$CONFIG_FILE" ]; then
rm "$CONFIG_FILE"
fi

cat <<EOF >${CONFIG_FILE}
cat <<EOF >"$CONFIG_FILE"
{
"label": "${AGENCY}_${CONTAINER_NAME}",
"walletId": "$WALLET_NAME",
Expand Down Expand Up @@ -154,7 +154,8 @@ cat <<EOF >${CONFIG_FILE}
"webhookUrl": "$WEBHOOK_HOST/wh/$AGENCY",
"adminPort": $ADMIN_PORT,
"tenancy": $TENANT,
"schemaFileServerURL": "$SCHEMA_FILE_SERVER_URL"
"schemaFileServerURL": "$SCHEMA_FILE_SERVER_URL",
"apiKey": "$AGENT_API_KEY"
}
EOF

Expand Down Expand Up @@ -238,7 +239,7 @@ if [ $? -eq 0 ]; then
container_logs=$(docker logs $(docker ps -q --filter "name=${AGENCY}_${CONTAINER_NAME}"))

# Extract the token from the logs using sed
token=$(echo "$container_logs" | sed -nE 's/.*API Token: ([^ ]+).*/\1/p')
token=$(echo "$container_logs" | sed -nE 's/.*** API Key: ([^ ]+).*/\1/p')

# Print the extracted token
echo "Token: $token"
Expand Down
75 changes: 72 additions & 3 deletions apps/agent-provisioning/AFJ/scripts/start_agent_ecs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ random_string=$(generate_random_string)
# Print the generated random string
echo "Random String: $random_string"

SERVICE_NAME="${AGENCY}-${CONTAINER_NAME}-service-${random_string}"
SERVICE_NAME="${CONTAINER_NAME}-service-test"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to revert this?

EXTERNAL_IP=$(echo "$2" | tr -d '[:space:]')
ADMIN_PORT_FILE="$PWD/agent-provisioning/AFJ/port-file/last-admin-port.txt"
INBOUND_PORT_FILE="$PWD/agent-provisioning/AFJ/port-file/last-inbound-port.txt"
Expand Down Expand Up @@ -153,7 +153,7 @@ CONTAINER_DEFINITIONS=$(
[
{
"name": "$CONTAINER_NAME",
"image": "${AFJ_IMAGE_URL}",
"image": "${AFJ_VERSION}",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might need some ENV changes in this case for ecs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@KambleSahil3 Please have a look

"cpu": 154,
"memory": 307,
"portMappings": [
Expand Down Expand Up @@ -194,6 +194,14 @@ CONTAINER_DEFINITIONS=$(
}
],
"volumesFrom": [],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/$TESKDEFINITION_FAMILY",
"awslogs-create-group": "true",
"awslogs-region": "ap-south-1",
"awslogs-stream-prefix": "ecs"
},
"ulimits": []
}
]
Expand Down Expand Up @@ -262,6 +270,67 @@ if [ $? -eq 0 ]; then
sleep 10
fi
done
# Describe the ECS service and filter by service name
service_description=$(aws ecs describe-services --service $SERVICE_NAME --cluster $CLUSTER_NAME --region $AWS_PUBLIC_REGION)
echo "service_description=$service_description"


# Extract Task ID from the service description events
task_id=$(echo "$service_description" | jq -r '.services[0].events[] | select(.message | test("has started 1 tasks")) | .message | capture("\\(task (?<id>[^)]+)\\)") | .id')
#echo "task_id=$task_id"

# to fetch log group of container
.............................................................
Copy link

@coderabbitai coderabbitai bot Aug 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix the placeholder text that could be misinterpreted as a command.

The line with dots is flagged by shellcheck as potentially being interpreted as a command. Replace with a proper comment.

-# to fetch log group of container 
-.............................................................
+# to fetch log group of container

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Shellcheck (0.10.0)

[warning] 283-283: This is interpreted as a command name ending with '.'. Double check syntax.

(SC2288)

🤖 Prompt for AI Agents
In apps/agent-provisioning/AFJ/scripts/start_agent_ecs.sh at line 283, replace
the line containing only dots with a proper shell comment to avoid it being
misinterpreted as a command by shellcheck. Use a hash symbol (#) followed by a
descriptive comment or leave it as an empty comment line.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@KambleSahil3 Can you please have a look at this

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

log_group=/ecs/$TESKDEFINITION_FAMILY
echo "log_group=$log_group"

# Get Log Stream Name
log_stream=ecs/$CONTAINER_NAME/$task_id

echo "logstrem=$log_stream"


# Fetch logs
#echo "$(aws logs get-log-events --log-group-name "/ecs/$TESKDEFINITION_FAMILY/$CONTAINER_NAME" --log-stream-name "$log_stream" --region $AWS_PUBLIC_REGION)"

# Check if the token folder exists, and create it if it doesn't
token_folder="$PWD/agent-provisioning/AFJ/token"
if [ ! -d "$token_folder" ]; then
mkdir -p "$token_folder"
fi

# Set maximum retry attempts
RETRIES=3

# Loop to attempt retrieving token from logs
# Loop to attempt retrieving token from logs
for attempt in $(seq 1 $RETRIES); do
echo "Attempt $attempt: Checking service logs for token..."

# Fetch logs and grep for API token
token=$(aws logs get-log-events \
--log-group-name "$log_group" \
--log-stream-name "$log_stream" \
--region ap-southeast-1 \
| grep -o '*** API Key: [^ ]*' \
| cut -d ' ' -f 3
)
# echo "token=$token"
if [ -n "$token" ]; then
echo "Token found: $token"
# Write token to a file
echo "{\"token\": \"$token\"}" > "$PWD/agent-provisioning/AFJ/token/${AGENCY}_${CONTAINER_NAME}.json"
break # Exit loop if token is found
else
echo "Token not found in logs. Retrying..."
if [ $attempt -eq $RETRIES ]; then
echo "Reached maximum retry attempts. Token not found."
fi
fi
# Add a delay of 10 seconds between retries
sleep 10
done


echo "Creating agent config"
cat <<EOF >${PWD}/agent-provisioning/AFJ/endpoints/${AGENCY}_${CONTAINER_NAME}.json
Expand All @@ -273,7 +342,7 @@ EOF

cat <<EOF >${PWD}/agent-provisioning/AFJ/token/${AGENCY}_${CONTAINER_NAME}.json
{
"token" : ""
"token" : "$token"
}
EOF

Expand Down
33 changes: 24 additions & 9 deletions apps/agent-provisioning/src/agent-provisioning.service.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-console */
import { Injectable, Logger, NotFoundException } from '@nestjs/common';
import { RpcException } from '@nestjs/microservices';
import { IWalletProvision } from './interface/agent-provisioning.interfaces';
Expand All @@ -9,25 +10,39 @@

@Injectable()
export class AgentProvisioningService {

constructor(
private readonly logger: Logger
) { }
constructor(private readonly logger: Logger) {}

/**
* Description: Wallet provision
* @param payload
* @param payload
* @returns Get DID and verkey
*/
async walletProvision(payload: IWalletProvision): Promise<object> {
try {

const { containerName, externalIp, orgId, seed, walletName, walletPassword, walletStorageHost, walletStoragePassword, walletStoragePort, walletStorageUser, webhookEndpoint, agentType, protocol, credoImage, tenant, indyLedger, inboundEndpoint } = payload;
const {
containerName,
externalIp,
orgId,
seed,
walletName,
walletPassword,
walletStorageHost,
walletStoragePassword,
walletStoragePort,

Check warning

Code scanning / CodeQL

Shell command built from environment values Medium

This shell command depends on an uncontrolled
absolute path
.

Copilot Autofix

AI 3 months ago

To fix this problem, we should avoid constructing a shell command string and passing it to exec. Instead, we should use execFile (or execFileSync/spawn), which allows us to specify the command and its arguments as an array, so that each argument is passed as-is to the underlying process without shell interpretation. This prevents shell injection and issues with spaces or special characters in arguments.

Detailed steps:

  • Parse the script path and all arguments as separate elements.
  • Build an array of arguments, ensuring each value is passed as a separate argument.
  • Replace exec(walletProvision, ...) with execFile(scriptPath, args, ...).
  • Import execFile from child_process.
  • Update the code to extract the script path and arguments from the original string.
  • No change to the rest of the logic.

Files/regions to change:

  • In apps/agent-provisioning/src/agent-provisioning.service.ts, lines 43–45: refactor the command construction and execution.
  • Add import for execFile if not already present.

Suggested changeset 1
apps/agent-provisioning/src/agent-provisioning.service.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/apps/agent-provisioning/src/agent-provisioning.service.ts b/apps/agent-provisioning/src/agent-provisioning.service.ts
--- a/apps/agent-provisioning/src/agent-provisioning.service.ts
+++ b/apps/agent-provisioning/src/agent-provisioning.service.ts
@@ -6,3 +6,3 @@
 import * as fs from 'fs';
-import { exec } from 'child_process';
+import { execFile } from 'child_process';
 dotenv.config();
@@ -42,5 +42,30 @@
         // The wallet provision command is used to invoke a shell script
-        const walletProvision = `${process.cwd() + process.env.AFJ_AGENT_SPIN_UP} ${orgId} "${externalIp}" "${walletName}" "${walletPassword}" ${seed} ${webhookEndpoint} ${walletStorageHost} ${walletStoragePort} ${walletStorageUser} ${walletStoragePassword} ${containerName} ${protocol} ${tenant} ${credoImage} "${indyLedger}" ${inboundEndpoint} ${process.env.SCHEMA_FILE_SERVER_URL} ${apiKey} ${process.env.AGENT_HOST} ${process.env.AWS_ACCOUNT_ID} ${process.env.S3_BUCKET_ARN} ${process.env.CLUSTER_NAME} ${process.env.TESKDEFINITION_FAMILY}`;
+        const scriptPath = process.cwd() + process.env.AFJ_AGENT_SPIN_UP;
+        const args = [
+          orgId,
+          externalIp,
+          walletName,
+          walletPassword,
+          seed,
+          webhookEndpoint,
+          walletStorageHost,
+          walletStoragePort,
+          walletStorageUser,
+          walletStoragePassword,
+          containerName,
+          protocol,
+          tenant,
+          credoImage,
+          indyLedger,
+          inboundEndpoint,
+          process.env.SCHEMA_FILE_SERVER_URL,
+          apiKey,
+          process.env.AGENT_HOST,
+          process.env.AWS_ACCOUNT_ID,
+          process.env.S3_BUCKET_ARN,
+          process.env.CLUSTER_NAME,
+          process.env.TESKDEFINITION_FAMILY
+        ];
         const spinUpResponse: object = new Promise(async (resolve) => {
-          await exec(walletProvision, async (err, stdout, stderr) => {
+          await execFile(scriptPath, args, async (err, stdout, stderr) => {
             this.logger.log(`shell script output: ${stdout}`);
EOF
@@ -6,3 +6,3 @@
import * as fs from 'fs';
import { exec } from 'child_process';
import { execFile } from 'child_process';
dotenv.config();
@@ -42,5 +42,30 @@
// The wallet provision command is used to invoke a shell script
const walletProvision = `${process.cwd() + process.env.AFJ_AGENT_SPIN_UP} ${orgId} "${externalIp}" "${walletName}" "${walletPassword}" ${seed} ${webhookEndpoint} ${walletStorageHost} ${walletStoragePort} ${walletStorageUser} ${walletStoragePassword} ${containerName} ${protocol} ${tenant} ${credoImage} "${indyLedger}" ${inboundEndpoint} ${process.env.SCHEMA_FILE_SERVER_URL} ${apiKey} ${process.env.AGENT_HOST} ${process.env.AWS_ACCOUNT_ID} ${process.env.S3_BUCKET_ARN} ${process.env.CLUSTER_NAME} ${process.env.TESKDEFINITION_FAMILY}`;
const scriptPath = process.cwd() + process.env.AFJ_AGENT_SPIN_UP;
const args = [
orgId,
externalIp,
walletName,
walletPassword,
seed,
webhookEndpoint,
walletStorageHost,
walletStoragePort,
walletStorageUser,
walletStoragePassword,
containerName,
protocol,
tenant,
credoImage,
indyLedger,
inboundEndpoint,
process.env.SCHEMA_FILE_SERVER_URL,
apiKey,
process.env.AGENT_HOST,
process.env.AWS_ACCOUNT_ID,
process.env.S3_BUCKET_ARN,
process.env.CLUSTER_NAME,
process.env.TESKDEFINITION_FAMILY
];
const spinUpResponse: object = new Promise(async (resolve) => {
await exec(walletProvision, async (err, stdout, stderr) => {
await execFile(scriptPath, args, async (err, stdout, stderr) => {
this.logger.log(`shell script output: ${stdout}`);
Copilot is powered by AI and may make mistakes. Always verify output.
walletStorageUser,
webhookEndpoint,
agentType,
protocol,
credoImage,
tenant,
indyLedger,
inboundEndpoint,
apiKey
} = payload;
if (agentType === AgentType.AFJ) {
// The wallet provision command is used to invoke a shell script
const walletProvision = `${process.cwd() + process.env.AFJ_AGENT_SPIN_UP} ${orgId} "${externalIp}" "${walletName}" "${walletPassword}" ${seed} ${webhookEndpoint} ${walletStorageHost} ${walletStoragePort} ${walletStorageUser} ${walletStoragePassword} ${containerName} ${protocol} ${tenant} ${credoImage} "${indyLedger}" ${inboundEndpoint} ${process.env.SCHEMA_FILE_SERVER_URL} ${process.env.AGENT_HOST} ${process.env.AWS_ACCOUNT_ID} ${process.env.S3_BUCKET_ARN} ${process.env.CLUSTER_NAME} ${process.env.TESKDEFINITION_FAMILY}`;
const walletProvision = `${process.cwd() + process.env.AFJ_AGENT_SPIN_UP} ${orgId} "${externalIp}" "${walletName}" "${walletPassword}" ${seed} ${webhookEndpoint} ${walletStorageHost} ${walletStoragePort} ${walletStorageUser} ${walletStoragePassword} ${containerName} ${protocol} ${tenant} ${credoImage} "${indyLedger}" ${inboundEndpoint} ${process.env.SCHEMA_FILE_SERVER_URL} ${apiKey} ${process.env.AGENT_HOST} ${process.env.AWS_ACCOUNT_ID} ${process.env.S3_BUCKET_ARN} ${process.env.CLUSTER_NAME} ${process.env.TESKDEFINITION_FAMILY}`;
const spinUpResponse: object = new Promise(async (resolve) => {

await exec(walletProvision, async (err, stdout, stderr) => {
this.logger.log(`shell script output: ${stdout}`);
if (stderr) {
Expand Down
Loading