Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed AWS to work when no secrets specified #686

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 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
9 changes: 8 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,14 @@ inputs:
default: 'false'
required: false
description: 'Skip the activation/deactivation of Unity. This assumes Unity is already activated.'

cloneDepth:
default: '50'
required: false
description: '[CloudRunner] Specifies the depth of the clone for the repository'
cloudRunnerRepoName:
default: 'game-ci/unity-builder'
required: false
description: '[CloudRunner] Specifies the repo for the unity builder. Useful if you forked the repo for testing, features, or fixes.'
outputs:
volume:
description: 'The Persistent Volume (PV) where the build artifacts have been stored by Kubernetes'
Expand Down
29 changes: 20 additions & 9 deletions dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion src/model/build-parameters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,15 @@ class BuildParameters {
public pullInputList!: string[];
public inputPullCommand!: string;
public cacheKey!: string;
public cloneDepth!: number;

public postBuildContainerHooks!: string;
public preBuildContainerHooks!: string;
public customJob!: string;
public runNumber!: string;
public branch!: string;
public githubRepo!: string;
public cloudRunnerRepoName!: string;
public gitSha!: string;
public logId!: string;
public buildGuid!: string;
Expand Down Expand Up @@ -194,7 +196,8 @@ class BuildParameters {
branch: Input.branch.replace('/head', '') || (await GitRepoReader.GetBranch()),
cloudRunnerBranch: CloudRunnerOptions.cloudRunnerBranch.split('/').reverse()[0],
cloudRunnerDebug: CloudRunnerOptions.cloudRunnerDebug,
githubRepo: (Input.githubRepo ?? (await GitRepoReader.GetRemote())) || 'game-ci/unity-builder',
githubRepo: (Input.githubRepo ?? (await GitRepoReader.GetRemote())) || CloudRunnerOptions.cloudRunnerRepoName,
cloudRunnerRepoName: CloudRunnerOptions.cloudRunnerRepoName,
isCliMode: Cli.isCliMode,
awsStackName: CloudRunnerOptions.awsStackName,
gitSha: Input.gitSha,
Expand All @@ -205,6 +208,7 @@ class BuildParameters {
pullInputList: CloudRunnerOptions.pullInputList,
kubeStorageClass: CloudRunnerOptions.kubeStorageClass,
cacheKey: CloudRunnerOptions.cacheKey,

maxRetainedWorkspaces: Number.parseInt(CloudRunnerOptions.maxRetainedWorkspaces),
useLargePackages: CloudRunnerOptions.useLargePackages,
useCompressionStrategy: CloudRunnerOptions.useCompressionStrategy,
Expand All @@ -218,6 +222,7 @@ class BuildParameters {
cacheUnityInstallationOnMac: Input.cacheUnityInstallationOnMac,
unityHubVersionOnMac: Input.unityHubVersionOnMac,
dockerWorkspacePath: Input.dockerWorkspacePath,
cloneDepth: Number.parseInt(CloudRunnerOptions.cloneDepth),
};
}

Expand Down
2 changes: 1 addition & 1 deletion src/model/cloud-runner/options/cloud-runner-folders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export class CloudRunnerFolders {
}

public static get unityBuilderRepoUrl(): string {
return `https://${CloudRunner.buildParameters.gitPrivateToken}@github.com/game-ci/unity-builder.git`;
return `https://${CloudRunner.buildParameters.gitPrivateToken}@github.com/${CloudRunner.buildParameters.unityBuilderRepo}.git`;
}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

⚠️ Potential issue

🧩 Analysis chain

Security: Avoid exposing git tokens in URLs.

The current implementation has several security concerns:

  1. Git tokens in URLs can be exposed through logs or error messages.
  2. Using a read-write token for cloning operations violates the principle of least privilege.
  3. The unityBuilderRepo value is not validated, potentially allowing injection attacks.

Consider these improvements:

  1. Use environment variables or git configuration for authentication:
-    return `https://${CloudRunner.buildParameters.gitPrivateToken}@github.com/${CloudRunner.buildParameters.unityBuilderRepo}.git`;
+    const repo = CloudRunner.buildParameters.unityBuilderRepo;
+    if (!repo.match(/^[a-zA-Z0-9-]+\/[a-zA-Z0-9-]+$/)) {
+      throw new Error('Invalid repository name format');
+    }
+    return `https://github.com/${repo}.git`;
  1. Configure git to use credentials from environment variables:

  2. Use a read-only token specifically for cloning operations.

Let's verify if the repository name format is consistently validated across the codebase:


🏁 Script executed:

git config --global credential.helper store
echo "https://github.com:$GITHUB_TOKEN" > ~/.git-credentials

Length of output: 72


🏁 Script executed:

#!/bin/bash
# Search for other instances where repository names are used in URLs
rg -A 5 'github\.com/.*\.git'

# Search for repository name validation
ast-grep --pattern 'if (!$_repo.match(/^[a-zA-Z0-9-]+\/[a-zA-Z0-9-]+$/)) { $$$_ }'

Length of output: 67754


Security issues found – Sensitive token exposure and lack of repository name validation

• The unityBuilderRepoUrl getter directly embeds the git private token in the URL, which can lead to undesired exposure through logs or error messages.
• Our search for consistent repository name validation (using regex checks) in the codebase returned no matches. This confirms that the proposed input validation is missing.
• Similar patterns exist in other getters (e.g., targetBuildRepoUrl), indicating that the issue is not isolated to a single occurrence.


public static get targetBuildRepoUrl(): string {
Expand Down
9 changes: 9 additions & 0 deletions src/model/cloud-runner/options/cloud-runner-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ class CloudRunnerOptions {
return CloudRunnerOptions.getInput('githubRepoName') || CloudRunnerOptions.githubRepo?.split(`/`)[1] || '';
}

static get cloudRunnerRepoName(): string {
return CloudRunnerOptions.getInput('cloudRunnerRepoName') || `game-ci/unity-builder`;
}

static get finalHooks(): string[] {
return CloudRunnerOptions.getInput('finalHooks')?.split(',') || [];
}
Expand All @@ -85,6 +89,7 @@ class CloudRunnerOptions {
static get githubRepo(): string | undefined {
return CloudRunnerOptions.getInput('GITHUB_REPOSITORY') || CloudRunnerOptions.getInput('GITHUB_REPO') || undefined;
}

static get branch(): string {
if (CloudRunnerOptions.getInput(`GITHUB_REF`)) {
return (
Expand Down Expand Up @@ -139,6 +144,10 @@ class CloudRunnerOptions {
return CloudRunnerOptions.getInput('customJob') || '';
}

static get cloneDepth(): string {
return CloudRunnerOptions.getInput('cloneDepth') || `50`;
}

// ### ### ###
// Custom commands from files parameters
// ### ### ###
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export class AWSCloudFormationTemplates {

public static getSecretDefinitionTemplate(p1: string, p2: string) {
return `
Secrets:
- Name: '${p1}'
ValueFrom: !Ref ${p2}Secret
`;
Expand Down
10 changes: 9 additions & 1 deletion src/model/cloud-runner/providers/aws/aws-job-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export class AWSJobStack {
);
taskDefCloudFormation = AWSCloudFormationTemplates.insertAtTemplate(
taskDefCloudFormation,
'p3 - container def',
'# template secrets p3 - container def',
AWSCloudFormationTemplates.getSecretDefinitionTemplate(secret.EnvironmentVariable, secret.ParameterKey),
);
}
Expand Down Expand Up @@ -113,9 +113,13 @@ export class AWSJobStack {
},
...secretsMappedToCloudFormationParameters,
];

CloudRunnerLogger.log(`TaskDef: ${taskDefCloudFormation}`);

CloudRunnerLogger.log(
`Starting AWS job with memory: ${CloudRunner.buildParameters.containerMemory} cpu: ${CloudRunner.buildParameters.containerCpu}`,
);

let previousStackExists = true;
while (previousStackExists) {
previousStackExists = false;
Expand All @@ -132,13 +136,17 @@ export class AWSJobStack {
}
}
}

const createStackInput: SDK.CloudFormation.CreateStackInput = {
StackName: taskDefStackName,
TemplateBody: taskDefCloudFormation,
Capabilities: ['CAPABILITY_IAM'],
Parameters: parameters,
};

CloudRunnerLogger.log(`StackInput: ${createStackInput}`);
try {
CloudRunnerLogger.log(`TaskDef Cloud formation: ${taskDefCloudFormation}`);
CloudRunnerLogger.log(`Creating job aws formation ${taskDefStackName}`);
await CF.createStack(createStackInput).promise();
await CF.waitFor('stackCreateComplete', { StackName: taskDefStackName }).promise();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,8 @@ Resources:
MountPoints:
- SourceVolume: efs-data
ContainerPath: !Ref EFSMountDirectory
ReadOnly: false
Secrets:
# template secrets p3 - container def
ReadOnly: false
# template secrets p3 - container def
LogConfiguration:
LogDriver: awslogs
Options:
Expand Down
4 changes: 3 additions & 1 deletion src/model/cloud-runner/remote-client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,9 @@ export class RemoteClient {
await CloudRunnerSystem.Run(`git config --global filter.lfs.process "git-lfs filter-process --skip"`);
try {
await CloudRunnerSystem.Run(
`git clone ${CloudRunnerFolders.targetBuildRepoUrl} ${path.basename(CloudRunnerFolders.repoPathAbsolute)}`,
`git clone --depth ${CloudRunnerOptions.cloneDepth} ${CloudRunnerFolders.targetBuildRepoUrl} ${path.basename(
CloudRunnerFolders.repoPathAbsolute,
)}`,
);
} catch (error: any) {
throw error;
Expand Down
4 changes: 2 additions & 2 deletions src/model/image-tag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class ImageTag {
public targetPlatform: string;
public builderPlatform: string;
public customImage: string;
public imageRollingVersion: number;
public imageRollingVersion: string;
public imagePlatformPrefix: string;

constructor(imageProperties: { [key: string]: string }) {
Expand Down Expand Up @@ -38,7 +38,7 @@ class ImageTag {
providerStrategy,
);
this.imagePlatformPrefix = ImageTag.getImagePlatformPrefixes(buildPlatform);
this.imageRollingVersion = Number(containerRegistryImageVersion); // Will automatically roll to the latest non-breaking version.
this.imageRollingVersion = containerRegistryImageVersion; // Will automatically roll to the latest non-breaking version.
}

static get versionPattern(): RegExp {
Expand Down